Decompiled source of Megabonk Level Editor v0.1.0
BepInEx/plugins/MegabonkLevels/MegabonkLevels.Mod.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers.Binary; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Actors.Enemies; using Assets.Scripts.Actors; using Assets.Scripts.Actors.Enemies; using Assets.Scripts.Actors.Player; using Assets.Scripts.Audio.Music; using Assets.Scripts.Game.Combat; using Assets.Scripts.Game.MapGeneration; using Assets.Scripts.Game.Other; using Assets.Scripts.Inventory__Items__Pickups; using Assets.Scripts.Inventory__Items__Pickups.Chests; using Assets.Scripts.Inventory__Items__Pickups.Items; using Assets.Scripts.Inventory__Items__Pickups.Items.ItemImplementations; using Assets.Scripts.Inventory__Items__Pickups.Stats; using Assets.Scripts.Inventory__Items__Pickups.Weapons; using Assets.Scripts.Managers; using Assets.Scripts.MapGeneration.ProceduralTiles; using Assets.Scripts.Menu.Shop; using Assets.Scripts.Saves___Serialization.Progression.Achievements; using Assets.Scripts.Saves___Serialization.SaveFiles.Configs; using Assets.Scripts.Settings___Saves.SaveFiles; using Assets.Scripts.Settings___Saves.SaveFiles.ConfigSaves; using Assets.Scripts.Steam; using Assets.Scripts.UI.Debug; using Assets.Scripts.UI.InGame.Levelup; using Assets.Scripts.UI.InGame.Rewards; using Assets.Scripts.Utility; using Assets.Scripts._Data.MapsAndStages; using BepInEx; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Utils.Collections; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using NLayer; using Rewired; using Steamworks; using TMPro; using Unity.AI.Navigation; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using Utility; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MegabonkLevels.Mod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+0ebefc8288bdf46075af01840000a6780e450789")] [assembly: AssemblyProduct("MegabonkLevels.Mod")] [assembly: AssemblyTitle("MegabonkLevels.Mod")] [assembly: AssemblyVersion("0.1.0.0")] namespace MegabonkLevels; public enum ActorKind { Enemy, Elite, Miniboss, StageBoss, FinalBoss } public static class ActorKinds { private const int Elite = 1; private const int Boss = 2; private const int StageBoss = 4; private const int SummonerMiniboss = 16; private const int FinalBoss = 32; public static ActorKind Of(int enemyFlags) { if ((enemyFlags & 0x20) != 0) { return ActorKind.FinalBoss; } if ((enemyFlags & 4) != 0) { return ActorKind.StageBoss; } if ((enemyFlags & 0x12) != 0) { return ActorKind.Miniboss; } if ((enemyFlags & 1) != 0) { return ActorKind.Elite; } return ActorKind.Enemy; } public static string Label(ActorKind kind) { return kind switch { ActorKind.FinalBoss => "final boss:", ActorKind.StageBoss => "boss:", ActorKind.Miniboss => "miniboss:", ActorKind.Elite => "elite:", _ => "enemy:", }; } public static bool IsBossTier(ActorKind kind) { if ((uint)(kind - 2) <= 2u) { return true; } return false; } } public static class AssetDump { private sealed class Walk { public HashSet<object> Path { get; } = new HashSet<object>(); public int MaxItems { get; } public int MaxNodes { get; } public int Nodes { get; set; } public int Level { get; set; } public Walk(int maxItems, int maxNodes) { MaxItems = maxItems; MaxNodes = maxNodes; } } public const int MaxDepth = 6; public const int DefaultMaxItems = 64; public const int DefaultMaxNodes = 20000; private const int MaxLevel = 24; private const BindingFlags Members = BindingFlags.Instance | BindingFlags.Public; public static JsonNode Describe(object value, int depth, int maxItems = 64, int maxNodes = 20000) { return Describe(value, Math.Min(depth, 6), new Walk(Math.Max(1, maxItems), Math.Max(1, maxNodes))); } private static JsonNode Describe(object value, int depth, Walk walk) { if (value == null) { return null; } if (IsPrimitive(value, out var primitive)) { return primitive; } if (walk.Nodes >= walk.MaxNodes || walk.Level >= 24) { return new JsonObject { ["$truncated"] = true }; } walk.Nodes++; if (walk.Path.Contains(value)) { return new JsonObject { ["$type"] = value.GetType().Name, ["name"] = ReadName(value), ["$cycle"] = true }; } if (value is IEnumerable sequence) { return DescribeSequence(sequence, depth, walk); } if (depth <= 0) { return JsonValue.Create(SafeText(value)); } Type type = value.GetType(); bool flag = Inherits(type, "UnityEngine.Object") && !Inherits(type, "UnityEngine.ScriptableObject"); walk.Path.Add(value); walk.Level++; JsonObject jsonObject = new JsonObject { ["$type"] = type.Name }; if (flag) { jsonObject["name"] = JsonValue.Create(ReadName(value)); } foreach (KeyValuePair<string, Func<object, object>> item in MembersOf(type, flag)) { jsonObject[item.Key] = DescribeMember(item, value, depth - 1, walk); } walk.Level--; walk.Path.Remove(value); if (flag) { jsonObject["$fieldsOnly"] = true; } return jsonObject; } private static bool Inherits(Type type, string fullName) { Type baseType = type.BaseType; while (baseType != null) { if (baseType.FullName == fullName) { return true; } baseType = baseType.BaseType; } return false; } private static JsonNode DescribeSequence(IEnumerable sequence, int depth, Walk walk) { walk.Path.Add(sequence); walk.Level++; JsonArray jsonArray = new JsonArray(); int num = 0; foreach (object item in sequence) { num++; if (jsonArray.Count < walk.MaxItems) { jsonArray.Add(Describe(item, depth, walk)); } } walk.Level--; walk.Path.Remove(sequence); if (num <= walk.MaxItems) { return jsonArray; } return new JsonObject { ["count"] = JsonValue.Create((long)num, (JsonNodeOptions?)null), ["truncated"] = true, ["items"] = jsonArray }; } private static JsonNode DescribeMember(KeyValuePair<string, Func<object, object>> member, object owner, int depth, Walk walk) { object value; try { value = member.Value(owner); } catch (Exception ex) { Exception ex2 = ((ex is TargetInvocationException { InnerException: not null } ex3) ? ex3.InnerException : ex); return JsonValue.Create("$error: " + ex2.GetType().Name + ": " + ex2.Message); } return Describe(value, depth, walk); } private static IEnumerable<KeyValuePair<string, Func<object, object>>> MembersOf(Type type, bool fieldsOnly) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo field in fields) { yield return new KeyValuePair<string, Func<object, object>>(field.Name, (object instance) => field.GetValue(instance)); } if (fieldsOnly) { yield break; } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo property in properties) { if (property.GetIndexParameters().Length == 0 && !(property.GetMethod == null)) { yield return new KeyValuePair<string, Func<object, object>>(property.Name, (object instance) => property.GetValue(instance)); } } } private static bool IsPrimitive(object value, out JsonNode primitive) { JsonValue jsonValue = ((value is string value2) ? JsonValue.Create(value2) : ((value is bool value3) ? JsonValue.Create(value3) : ((value is Enum value4) ? JsonValue.Create(Convert.ToInt64(value4)) : ((!(value is sbyte) && !(value is byte) && !(value is short) && !(value is ushort) && !(value is int) && !(value is uint) && !(value is long)) ? ((value is ulong value5) ? JsonValue.Create(value5) : ((value is float value6) ? JsonValue.Create(value6) : ((!(value is double) && !(value is decimal)) ? ((!(value is char c)) ? null : JsonValue.Create(c.ToString())) : JsonValue.Create(Convert.ToDouble(value))))) : JsonValue.Create(Convert.ToInt64(value)))))); primitive = jsonValue; bool flag = primitive != null; if (!flag) { bool flag2 = ((value is string || value is bool) ? true : false); flag = flag2; } return flag; } private static string ReadName(object value) { try { return (value.GetType().GetProperty("name", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string) ?? (value.GetType().GetField("name", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string); } catch (Exception ex) { return "$error: " + ex.GetType().Name + ": " + ex.Message; } } private static string SafeText(object value) { try { return value.ToString() ?? value.GetType().Name; } catch (Exception ex) { return "$error: " + ex.GetType().Name + ": " + ex.Message; } } } public static class BlankLevel { public const int DefaultSize = 7; public const int MinimumSize = 3; private const float SpawnBodyY = 2f; private const float BossSpawnerRotationY = 270f; public static LevelFile Create(EMap map, int stageIndex, int tier, int size, float spacing, string gameBuildId) { if (size < 3) { throw new ArgumentException($"A from-scratch grid must be at least {3} by {3}, got {size}.", "size"); } List<AuthoredCell> list = new List<AuthoredCell>(size * size); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { list.Add(new AuthoredCell(i, j, 0)); } } int num = size / 2; int cellX = Math.Min(num + 2, size - 1); (float X, float Z) tuple = PositionReadout.CellCentre(num, num, size, size, spacing); float item = tuple.X; float item2 = tuple.Z; (float X, float Z) tuple2 = PositionReadout.CellCentre(cellX, num, size, size, spacing); float item3 = tuple2.X; float item4 = tuple2.Z; Dictionary<string, string> packs = new Dictionary<string, string>(); EditOp[] edits = Array.Empty<EditOp>(); LevelGrid? grid = new LevelGrid(size, size, list); SpawnPoint? spawn = new SpawnPoint(new float[3] { item, 2f, item2 }, new float[3]); SpawnPoint? bossSpawner = new SpawnPoint(new float[3] { item3, 0f, item4 }, new float[3] { 0f, 270f, 0f }); return new LevelFile(4, gameBuildId, map, stageIndex, tier, 0, packs, edits, NoGrass: false, null, null, null, null, null, null, null, null, null, GrindRequiresSlide: false, null, null, RandomizeShadyGuy: false, RandomizeChests: false, RandomizeMoai: false, 0, null, null, null, null, null, null, null, null, null, null, null, null, "none", grid, spawn, bossSpawner); } } public static class BossEventLog { public static string Format(string eventName) { return "BossEvents: " + eventName; } public static string Format<T>(string eventName, T value) { return $"BossEvents: {eventName} {value}"; } } public static class BossEventPatch { public static void Install(ModLogger logger) { InteractableBossSpawner.A_BossSpawned += Action.op_Implicit((Action)delegate { logger.Msg(BossEventLog.Format("A_BossSpawned")); }); InteractableBossSpawner.A_BossDefeated += Action<bool>.op_Implicit((Action<bool>)delegate(bool flag) { logger.Msg(BossEventLog.Format("A_BossDefeated", flag)); }); InteractableBossSpawner.A_NumBossesDefeated += Action<int>.op_Implicit((Action<int>)delegate(int count) { logger.Msg(BossEventLog.Format("A_NumBossesDefeated", count)); }); GraveyardBossRoom.A_BossDied += Action.op_Implicit((Action)delegate { logger.Msg(BossEventLog.Format("A_BossDied")); }); EnemyManager.A_StageBossDied += Action.op_Implicit((Action)delegate { logger.Msg(BossEventLog.Format("A_StageBossDied")); }); } } public enum BossPoolKind { None, Boss, Miniboss } public static class BossPools { private const int BossBit = 2; private const int StageBossBit = 4; private const int SummonerMinibossBit = 16; private const int FinalBossBit = 32; public const int MaxEntries = 64; public static BossPoolKind Classify(int flags) { if ((flags & 0x24) == 0) { if ((flags & 0x12) == 0) { return BossPoolKind.None; } return BossPoolKind.Miniboss; } return BossPoolKind.Boss; } public static string Pick(IReadOnlyList<string> pool, Random random, ISet<string> used = null) { List<string> list = pool?.Where((string name) => used == null || !used.Contains(name)).ToList(); if (list == null || list.Count <= 0) { return null; } string text = list[random.Next(list.Count)]; used?.Add(text); return text; } public static void Validate(IReadOnlyList<string> pool, string field) { if (pool == null || (pool.Count <= 64 && !pool.Any(string.IsNullOrWhiteSpace))) { return; } throw new ArgumentException($"{field} lists up to {64} enemy names, none blank."); } } public static class BossPoolPatch { [HarmonyPatch(typeof(EnemyManager), "SpawnBoss")] private static class SpawnBossDrawsFromThePool { private static void Prefix(ref EEnemy eEnemy, EEnemyFlag enemyFlag) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected I4, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (!CustomLevelState.IsActive) { return; } LevelFile currentSettings = LiveEditPatch.CurrentSettings; BossPoolKind bossPoolKind = BossPools.Classify((int)enemyFlag); IReadOnlyList<string> readOnlyList = bossPoolKind switch { BossPoolKind.Boss => currentSettings.BossPool, BossPoolKind.Miniboss => currentSettings.MinibossPool, _ => null, }; string text = LiveEditPatch.RunRandom.PickBoss(readOnlyList); EEnemy result; if (text == null) { if (readOnlyList != null && readOnlyList.Count > 0) { _logger?.Msg($"BossPool: {bossPoolKind} pool exhausted; keeping {eEnemy} (flags {enemyFlag})"); } } else if (!Enum.TryParse<EEnemy>(text, ignoreCase: true, out result)) { if (s_unknown.Add(text)) { _logger?.Warning("BossPool: unknown enemy '" + text + "' ignored"); } } else { _logger?.Msg($"BossPool: {bossPoolKind} spawn of {eEnemy} (flags {enemyFlag}) replaced by {result}"); eEnemy = (EEnemy)(int)result; } } } private static ModLogger _logger; private static readonly HashSet<string> s_unknown = new HashSet<string>(); public static void Install(ModLogger logger) { _logger = logger; } } public readonly record struct Vec3(float X, float Y, float Z); public static class BossSpawnRedirect { public const int ArmWindowFrames = 2; public const float MinDistanceFromSpawner = 35f; public const float MaxDistanceFromSpawner = 68f; public const float MinSpacingBetweenCopies = 20f; public const float KillFloorMargin = 5f; public const float BoxFloorBelowSpawner = 2f; public const float BoxRoofAboveSpawner = 10f; public static bool ShouldArm(bool customLevelActive, bool fromScratch, bool redirectRequested) { if (customLevelActive) { return !fromScratch || redirectRequested; } return false; } public static bool IsInsideBossBox(Vec3 pos, Vec3 spawner) { if (XzDistance(pos, spawner) < 35f && pos.Y >= spawner.Y - 2f) { return pos.Y <= spawner.Y + 10f; } return false; } public static int ExpectedMoves(int bossCurses) { return Math.Max(1, 1 + bossCurses); } public static bool ShouldConsume(int? armedFrame, int frame, int windowFrames = 2) { if (armedFrame.HasValue && frame >= armedFrame.Value) { return frame <= armedFrame.Value + windowFrames; } return false; } public static bool ShouldExpire(int? armedFrame, int expectedMoves, int moveCount, int frame, int windowFrames = 2) { if (armedFrame.HasValue) { if (moveCount < expectedMoves) { return frame > armedFrame.Value + windowFrames; } return true; } return false; } public static List<Vec3> CandidateRing(Vec3 spawner, int seed, int count) { Random random = new Random(seed); List<Vec3> list = new List<Vec3>(count); for (int i = 0; i < count; i++) { float x = (float)(random.NextDouble() * 2.0 * Math.PI); float num = 35f + (float)(random.NextDouble() * 33.0); list.Add(new Vec3(spawner.X + MathF.Cos(x) * num, spawner.Y, spawner.Z + MathF.Sin(x) * num)); } return list; } public static bool SpotUsable(Vec3 floorPoint, Vec3 spawner, float killFloorY, IReadOnlyList<Vec3> taken) { if (XzDistance(floorPoint, spawner) < 35f) { return false; } if (floorPoint.Y < killFloorY + 5f) { return false; } foreach (Vec3 item in taken) { if (XzDistance(floorPoint, item) < 20f) { return false; } } return true; } public static bool PickSpot(IReadOnlyList<Vec3> usable, IReadOnlyList<Vec3> taken, out Vec3 spot) { return Maximin.Pick(usable, taken, XzDistance, out spot); } public static Vec3 FloorPlacement(Vec3 floorPoint, Vec3 requestedPosition, Vec3 actualPosition) { return new Vec3(floorPoint.X, floorPoint.Y + actualPosition.Y - requestedPosition.Y, floorPoint.Z); } public static float XzDistance(Vec3 a, Vec3 b) { float num = a.X - b.X; float num2 = a.Z - b.Z; return MathF.Sqrt(num * num + num2 * num2); } } public static class BossSpawnRedirectPatch { [HarmonyPatch(typeof(InteractableBossSpawner), "Interact")] private static class InteractArmsTheRedirect { private static void Prefix(InteractableBossSpawner __instance) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (BossSpawnRedirect.ShouldArm(CustomLevelState.IsActive, FromScratchGenerationPatch.ActiveLevel.HasValue, FromScratchGenerationPatch.ActiveLevel?.BossRedirect ?? false) && !((Object)(object)__instance == (Object)null)) { _expectedMoves = BossSpawnRedirect.ExpectedMoves(((Object)(object)GameManager.Instance != (Object)null) ? GameManager.Instance.bossCurses : 0); _moveCount = 0; _taken.Clear(); _movedBosses.Clear(); Vector3 position = ((Component)__instance).transform.position; _spawner = new Vec3(position.x, position.y, position.z); _seed = Environment.TickCount; _armedFrame = Time.frameCount; _logger?.Msg($"BossSpawnRedirect: armed at spawner ({position.x:0.###}, {position.y:0.###}, {position.z:0.###}), expecting {_expectedMoves} boss(es) at frame {Time.frameCount}."); } } } [HarmonyPatch(typeof(EnemyManager), "SpawnBoss")] private static class SpawnBossMovesTheBoss { private static void Postfix(Enemy __result, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MoveIfArmed(__result, pos, "SpawnBoss"); } } [HarmonyPatch(typeof(EnemyManager), "SpawnEnemy", new Type[] { typeof(EnemyData), typeof(Vector3), typeof(int), typeof(bool), typeof(EEnemyFlag), typeof(bool), typeof(float) })] private static class SpawnEnemyMovesTheBoss { private static void Postfix(Enemy __result, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MoveIfArmed(__result, pos, "SpawnEnemy"); } } private const int CandidatesPerBoss = 48; private const int SeedPerCopy = 7919; private static ModLogger _logger; private static int? _armedFrame; private static int _expectedMoves; private static int _moveCount; private static Vec3 _spawner; private static int _seed; private static readonly List<Vec3> _taken = new List<Vec3>(); private static readonly HashSet<IntPtr> _movedBosses = new HashSet<IntPtr>(); public static void Install(ModLogger logger) { _logger = logger; } public static void Disarm() { _armedFrame = null; _expectedMoves = 0; _moveCount = 0; _taken.Clear(); _movedBosses.Clear(); } private static void MoveIfArmed(Enemy boss, Vector3 requested, string via) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) if (!_armedFrame.HasValue) { MoveMinibossOutOfTheBox(boss, requested, via); return; } int frameCount = Time.frameCount; if (BossSpawnRedirect.ShouldExpire(_armedFrame, _expectedMoves, _moveCount, frameCount)) { if (_moveCount < _expectedMoves) { _logger?.Msg($"BossSpawnRedirect: window expired at frame {frameCount} after {_moveCount}/{_expectedMoves} moves."); } _armedFrame = null; } else { if (!BossSpawnRedirect.ShouldConsume(_armedFrame, frameCount) || (Object)(object)boss == (Object)null || !boss.IsBoss() || !_movedBosses.Add(((Il2CppObjectBase)boss).Pointer)) { return; } if (!TryFindSpot(boss, _spawner, _seed + _moveCount * 7919, _taken, out var floorPoint)) { _logger?.Msg("BossSpawnRedirect: no usable interior spot for the boss spawned via " + via + ", left alone."); return; } Vector3 position = ((Component)boss).transform.position; Vec3 vec = BossSpawnRedirect.FloorPlacement(floorPoint, new Vec3(requested.x, requested.y, requested.z), new Vec3(position.x, position.y, position.z)); ((Component)boss).transform.position = new Vector3(vec.X, vec.Y, vec.Z); if ((Object)(object)boss.rb != (Object)null) { boss.rb.velocity = Vector3.zero; } _taken.Add(floorPoint); _moveCount++; _logger?.Msg($"BossSpawnRedirect: boss {_moveCount}/{_expectedMoves} moved from ({position.x:0.###}, {position.y:0.###}, {position.z:0.###}) to ({vec.X:0.###}, {vec.Y:0.###}, {vec.Z:0.###}) via {via}."); if (BossSpawnRedirect.ShouldExpire(_armedFrame, _expectedMoves, _moveCount, frameCount)) { _armedFrame = null; } } } private static void MoveMinibossOutOfTheBox(Enemy boss, Vector3 requested, string via) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)boss == (Object)null || !boss.IsBoss() || !BossSpawnRedirect.ShouldArm(CustomLevelState.IsActive, FromScratchGenerationPatch.ActiveLevel.HasValue, FromScratchGenerationPatch.ActiveLevel?.BossRedirect ?? false)) { return; } InteractableBossSpawner val = Object.FindObjectOfType<InteractableBossSpawner>(); if ((Object)(object)val == (Object)null) { return; } Vector3 position = ((Component)val).transform.position; Vec3 spawner = new Vec3(position.x, position.y, position.z); Vector3 position2 = ((Component)boss).transform.position; if (!BossSpawnRedirect.IsInsideBossBox(new Vec3(position2.x, position2.y, position2.z), spawner)) { return; } if (!TryFindSpot(boss, spawner, Environment.TickCount, Array.Empty<Vec3>(), out var floorPoint)) { _logger?.Msg("BossSpawnRedirect: no usable interior spot for the miniboss spawned via " + via + ", left alone."); return; } Vec3 vec = BossSpawnRedirect.FloorPlacement(floorPoint, new Vec3(requested.x, requested.y, requested.z), new Vec3(position2.x, position2.y, position2.z)); ((Component)boss).transform.position = new Vector3(vec.X, vec.Y, vec.Z); if ((Object)(object)boss.rb != (Object)null) { boss.rb.velocity = Vector3.zero; } ModLogger logger = _logger; if (logger != null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(62, 8); defaultInterpolatedStringHandler.AppendLiteral("BossSpawnRedirect: miniboss "); EnemyData enemyData = boss.enemyData; defaultInterpolatedStringHandler.AppendFormatted((enemyData != null) ? new EEnemy?(enemyData.enemyName) : ((EEnemy?)null)); defaultInterpolatedStringHandler.AppendLiteral(" moved from ("); defaultInterpolatedStringHandler.AppendFormatted(position2.x, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(position2.y, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(position2.z, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(") to "); defaultInterpolatedStringHandler.AppendLiteral("("); defaultInterpolatedStringHandler.AppendFormatted(vec.X, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(vec.Y, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(vec.Z, "0.###"); defaultInterpolatedStringHandler.AppendLiteral(") via "); defaultInterpolatedStringHandler.AppendFormatted(via); defaultInterpolatedStringHandler.AppendLiteral("."); logger.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); } } private static bool TryFindSpot(Enemy boss, Vec3 spawner, int seed, IReadOnlyList<Vec3> taken, out Vec3 floorPoint) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) floorPoint = default(Vec3); float num = LiveEditPatch.KillFloorY ?? float.MinValue; float top = spawner.Y + 20f; List<Vec3> list = new List<Vec3>(); foreach (Vec3 item in BossSpawnRedirect.CandidateRing(spawner, seed, 48)) { if (BossSpawnRedirect.SpotUsable(item, spawner, num, taken) && PlacementProbe.HighestFloor(item.X, item.Z, top, (num == float.MinValue) ? (-100f) : (num - 5f), ((Component)boss).transform, out var floor)) { Vec3 vec = new Vec3(item.X, floor.y, item.Z); if (BossSpawnRedirect.SpotUsable(vec, spawner, num, taken) && PlacementProbe.ClearPoint(new Vector3(vec.X, vec.Y, vec.Z))) { list.Add(vec); } } } return BossSpawnRedirect.PickSpot(list, taken, out floorPoint); } } public static class CameraOverride { private static CameraPose? _pose; private static bool _hasSaved; private static Vector3 _savedLocalPosition; private static Quaternion _savedLocalRotation; public static void Set(CameraPose pose) { _pose = pose; } public static void Clear() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) _pose = null; if (_hasSaved) { _hasSaved = false; PlayerCamera instance = PlayerCamera.Instance; Camera val = ((instance != null) ? instance.camera : null); if ((Object)(object)val != (Object)null) { ((Component)val).transform.localPosition = _savedLocalPosition; ((Component)val).transform.localRotation = _savedLocalRotation; } } } public static void Apply() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) CameraPose? pose = _pose; if (!pose.HasValue) { return; } CameraPose valueOrDefault = pose.GetValueOrDefault(); PlayerCamera instance = PlayerCamera.Instance; Camera val = ((instance != null) ? instance.camera : null); if (!((Object)(object)val == (Object)null)) { Transform transform = ((Component)val).transform; if (!_hasSaved) { _savedLocalPosition = transform.localPosition; _savedLocalRotation = transform.localRotation; _hasSaved = true; } transform.position = new Vector3(valueOrDefault.X, valueOrDefault.Y, valueOrDefault.Z); transform.rotation = Quaternion.Euler(valueOrDefault.Rx, valueOrDefault.Ry, valueOrDefault.Rz); } } } public enum CatalogNamespace { GameAsset, Bundle } public readonly record struct CatalogId(CatalogNamespace ns, IReadOnlyList<string> segments) { private static readonly Regex SegmentPattern = new Regex("^[A-Za-z0-9_-]+$", RegexOptions.Compiled); private const string BundlePrefix = "bundle:"; public static CatalogId Parse(string raw) { if (!TryParse(raw, out var id, out var error)) { throw new ArgumentException(error, "raw"); } return id; } public static bool TryParse(string raw, out CatalogId id, out string error) { id = default(CatalogId); if (string.IsNullOrWhiteSpace(raw)) { error = "catalogId must not be empty or whitespace."; return false; } CatalogNamespace ns; string text; if (raw.StartsWith("bundle:", StringComparison.Ordinal)) { ns = CatalogNamespace.Bundle; text = raw.Substring("bundle:".Length); } else { if (raw.Contains(':')) { error = "catalogId '" + raw + "' has an unknown namespace prefix; only 'bundle:' is recognized."; return false; } ns = CatalogNamespace.GameAsset; text = raw; } string[] array = text.Split('/'); string[] array2 = array; foreach (string text2 in array2) { if (text2.Length == 0) { error = "catalogId '" + raw + "' contains an empty segment (check for leading/trailing or doubled '/')."; return false; } if (!SegmentPattern.IsMatch(text2)) { error = $"catalogId '{raw}' has invalid character(s) in segment '{text2}'; only letters, digits, '_', and '-' are allowed."; return false; } } if (array.Length < 2) { error = $"catalogId '{raw}' has too few segments; must have at least 2, got {array.Length}."; return false; } id = new CatalogId(ns, array); error = null; return true; } public string Serialize() { return Namespace switch { CatalogNamespace.Bundle => "bundle:" + string.Join("/", Segments), CatalogNamespace.GameAsset => string.Join("/", Segments), _ => throw new ArgumentException($"Unknown {"CatalogNamespace"}: {Namespace}"), }; } public bool Equals(CatalogId other) { if (Namespace == other.Namespace) { if (Segments != null && other.Segments != null) { return Segments.SequenceEqual(other.Segments); } return Segments == other.Segments; } return false; } public override int GetHashCode() { HashCode hashCode = default(HashCode); hashCode.Add(Namespace); if (Segments != null) { foreach (string segment in Segments) { hashCode.Add(segment); } } return hashCode.ToHashCode(); } } public static class CatalogPrefabs { private static MapData _lastMap; public static MapData TryFindMap(EMap map) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 if ((Object)(object)_lastMap != (Object)null && (int)_lastMap.eMap == (int)map) { return _lastMap; } foreach (MapData item in Resources.FindObjectsOfTypeAll<MapData>()) { if ((Object)(object)item != (Object)null && (int)item.eMap == (int)map) { _lastMap = item; return item; } } return null; } public static MapData FindMap(EMap map) { return TryFindMap(map) ?? throw new ArgumentException($"No MapData for map {map}."); } public static IReadOnlyList<PaletteMapCatalog> DescribeAll(MapData current, SpawnInteractables interactables, RandomObjectPlacer placer) { List<PaletteMapCatalog> list = new List<PaletteMapCatalog>(); if ((Object)(object)current != (Object)null) { list.Add(Describe(current, interactables, placer)); } foreach (MapData item in OtherLoadedMaps(current)) { list.Add(Describe(item, null, null)); } return list; } public static PaletteMapCatalog Describe(MapData mapData, SpawnInteractables interactables, RandomObjectPlacer placer) { //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Expected I4, but got Unknown PaletteStageCatalog[] array = new PaletteStageCatalog[((Il2CppArrayBase<StageData>)(object)mapData.stages)?.Length ?? 0]; for (int i = 0; i < array.Length; i++) { StageData val = ((Il2CppArrayBase<StageData>)(object)mapData.stages)[i]; Il2CppReferenceArray<RandomMapObject> randomMapObjects = val.randomMapObjects; int[] array2 = new int[((Il2CppArrayBase<RandomMapObject>)(object)randomMapObjects)?.Length ?? 0]; for (int j = 0; j < array2.Length; j++) { array2[j] = ((Il2CppArrayBase<GameObject>)(object)((Il2CppArrayBase<RandomMapObject>)(object)randomMapObjects)[j].prefabs)?.Length ?? 0; } int num = i; StageTilePrefabs stageTilePrefabs = val.stageTilePrefabs; int valueOrDefault = ((stageTilePrefabs != null) ? ((Il2CppArrayBase<GameObject>)(object)stageTilePrefabs.flatTilePrefabs)?.Length : ((int?)null)).GetValueOrDefault(); StageTilePrefabs stageTilePrefabs2 = val.stageTilePrefabs; array[num] = new PaletteStageCatalog(array2, valueOrDefault, ((stageTilePrefabs2 != null) ? ((Il2CppArrayBase<GameObject>)(object)stageTilePrefabs2.mapSpecificTilesPrefabs)?.Length : ((int?)null)).GetValueOrDefault()); } Il2CppReferenceArray<RandomMapObject> randomObjectsOverride = mapData.randomObjectsOverride; int[] array3 = new int[((Il2CppArrayBase<RandomMapObject>)(object)randomObjectsOverride)?.Length ?? 0]; for (int k = 0; k < array3.Length; k++) { int num2 = k; RandomMapObject obj = ((Il2CppArrayBase<RandomMapObject>)(object)randomObjectsOverride)[k]; array3[num2] = ((obj != null) ? ((Il2CppArrayBase<GameObject>)(object)obj.prefabs)?.Length : ((int?)null)).GetValueOrDefault(); } EMap eMap = mapData.eMap; int shrineCount = ((Il2CppArrayBase<GameObject>)(object)mapData.shrines)?.Length ?? 0; bool hasChest = (Object)(object)((interactables != null) ? interactables.chest : null) != (Object)null; bool hasChestFree = (Object)(object)((interactables != null) ? interactables.chestFree : null) != (Object)null; int valueOrDefault2 = ((interactables == null) ? ((int?)null) : ((Il2CppArrayBase<GameObject>)(object)interactables.rails)?.Length).GetValueOrDefault(); int hasBoombox; if ((Object)(object)interactables != (Object)null) { EffectManager instance = EffectManager.Instance; hasBoombox = (((Object)(object)((instance != null) ? instance.boomboxQuest : null) != (Object)null) ? 1 : 0); } else { hasBoombox = 0; } int? obj2; if (placer == null) { obj2 = null; } else { RandomMapObject chargeShrineSpawns = placer.chargeShrineSpawns; obj2 = ((chargeShrineSpawns == null) ? ((int?)null) : ((Il2CppArrayBase<GameObject>)(object)chargeShrineSpawns.prefabs)?.Length); } int? num3 = obj2; int valueOrDefault3 = num3.GetValueOrDefault(); int? obj3; if (placer == null) { obj3 = null; } else { RandomMapObject greedShrineSpawns = placer.greedShrineSpawns; obj3 = ((greedShrineSpawns == null) ? ((int?)null) : ((Il2CppArrayBase<GameObject>)(object)greedShrineSpawns.prefabs)?.Length); } num3 = obj3; return new PaletteMapCatalog((EMap)eMap, array, shrineCount, hasChest, hasChestFree, valueOrDefault2, (byte)hasBoombox != 0, valueOrDefault3, num3.GetValueOrDefault(), array3); } public static GameObject Resolve(CatalogRoute route, SpawnInteractables interactables, RandomObjectPlacer placer) { switch (route.Kind) { case CatalogRouteKind.Chest: return interactables.chest; case CatalogRouteKind.ChestFree: return interactables.chestFree; case CatalogRouteKind.Boombox: return EffectManager.Instance.boomboxQuest; case CatalogRouteKind.Rail: return ((Il2CppArrayBase<GameObject>)(object)interactables.rails)[route.Index]; case CatalogRouteKind.ChargeShrine: { object obj2; if (placer == null) { obj2 = null; } else { RandomMapObject chargeShrineSpawns = placer.chargeShrineSpawns; obj2 = ((chargeShrineSpawns != null) ? chargeShrineSpawns.prefabs : null); } return PrefabAt(Il2CppArrayBase<GameObject>.op_Implicit((Il2CppArrayBase<GameObject>)obj2), route.Index); } case CatalogRouteKind.GreedShrine: { object obj3; if (placer == null) { obj3 = null; } else { RandomMapObject greedShrineSpawns = placer.greedShrineSpawns; obj3 = ((greedShrineSpawns != null) ? greedShrineSpawns.prefabs : null); } return PrefabAt(Il2CppArrayBase<GameObject>.op_Implicit((Il2CppArrayBase<GameObject>)obj3), route.Index); } default: { MapData val = FindMap(route.Map); if (route.Kind == CatalogRouteKind.Shrine) { return ((Il2CppArrayBase<GameObject>)(object)val.shrines)[route.Index]; } if (route.Kind == CatalogRouteKind.RandomObjectOverride) { Il2CppReferenceArray<RandomMapObject> randomObjectsOverride = val.randomObjectsOverride; if (randomObjectsOverride == null || route.Index >= ((Il2CppArrayBase<RandomMapObject>)(object)randomObjectsOverride).Length) { return null; } RandomMapObject obj = ((Il2CppArrayBase<RandomMapObject>)(object)randomObjectsOverride)[route.Index]; return PrefabAt(Il2CppArrayBase<GameObject>.op_Implicit((Il2CppArrayBase<GameObject>)(object)((obj != null) ? obj.prefabs : null)), route.SubIndex); } StageData val2 = ((Il2CppArrayBase<StageData>)(object)val.stages)[route.Stage]; return (GameObject)(route.Kind switch { CatalogRouteKind.RandomMapObject => ((Il2CppArrayBase<GameObject>)(object)((Il2CppArrayBase<RandomMapObject>)(object)val2.randomMapObjects)[route.Index].prefabs)[route.SubIndex], CatalogRouteKind.FlatTilePrefab => ((Il2CppArrayBase<GameObject>)(object)val2.stageTilePrefabs.flatTilePrefabs)[route.Index], CatalogRouteKind.SpecificTilePrefab => ((Il2CppArrayBase<GameObject>)(object)val2.stageTilePrefabs.mapSpecificTilesPrefabs)[route.Index], _ => throw new ArgumentException($"Unhandled catalog route kind {route.Kind}."), }); } } } private static IEnumerable<MapData> OtherLoadedMaps(MapData current) { HashSet<int> seen = new HashSet<int>(); return from mapData in (IEnumerable<MapData>)Resources.FindObjectsOfTypeAll<MapData>() where (Object)(object)mapData != (Object)null && mapData != current && seen.Add((int)mapData.eMap) orderby (int)mapData.eMap select mapData; } private static GameObject PrefabAt(GameObject[] prefabs, int index) { if (prefabs == null || index < 0 || index >= prefabs.Length) { return null; } return prefabs[index]; } } public enum CatalogRouteKind { RandomMapObject, FlatTilePrefab, SpecificTilePrefab, Shrine, RandomObjectOverride, Chest, ChestFree, Boombox, Rail, ChargeShrine, GreedShrine } public readonly record struct CatalogRoute(CatalogRouteKind Kind, EMap Map, int Stage, int Index, int SubIndex) { public static CatalogRoute Parse(CatalogId id) { if (id.Namespace != CatalogNamespace.GameAsset) { throw new ArgumentException("'" + id.Serialize() + "' is not a game-asset catalogId.", "id"); } IReadOnlyList<string> segments = id.Segments; if (segments.Count == 2 && segments[0] == "interactable") { return segments[1] switch { "chest" => new CatalogRoute(CatalogRouteKind.Chest, EMap.None, 0, 0, 0), "chestFree" => new CatalogRoute(CatalogRouteKind.ChestFree, EMap.None, 0, 0, 0), "boombox" => new CatalogRoute(CatalogRouteKind.Boombox, EMap.None, 0, 0, 0), _ => throw Unresolvable(id), }; } if (segments.Count == 3 && segments[0] == "interactable" && segments[1] == "rail") { return new CatalogRoute(CatalogRouteKind.Rail, EMap.None, 0, Number(segments[2], id), 0); } if (segments.Count == 3 && segments[0] == "interactable" && segments[1] == "chargeShrine") { return new CatalogRoute(CatalogRouteKind.ChargeShrine, EMap.None, 0, Number(segments[2], id), 0); } if (segments.Count == 3 && segments[0] == "interactable" && segments[1] == "greedShrine") { return new CatalogRoute(CatalogRouteKind.GreedShrine, EMap.None, 0, Number(segments[2], id), 0); } EMap map = ParseMap(segments[0], id); if (segments.Count == 3 && segments[1] == "shrines") { return new CatalogRoute(CatalogRouteKind.Shrine, map, 0, Number(segments[2], id), 0); } if (segments.Count == 4 && segments[1] == "randomObjectsOverride") { return new CatalogRoute(CatalogRouteKind.RandomObjectOverride, map, 0, Number(segments[2], id), Number(segments[3], id)); } if (segments.Count >= 4 && segments[1].StartsWith("stage", StringComparison.Ordinal)) { int stage = Number(segments[1].Substring("stage".Length), id); if (segments.Count == 5 && segments[2] == "randomMapObjects") { return new CatalogRoute(CatalogRouteKind.RandomMapObject, map, stage, Number(segments[3], id), Number(segments[4], id)); } if (segments.Count == 5 && segments[2] == "stageTilePrefabs" && segments[3] == "flat") { return new CatalogRoute(CatalogRouteKind.FlatTilePrefab, map, stage, Number(segments[4], id), 0); } if (segments.Count == 5 && segments[2] == "stageTilePrefabs" && segments[3] == "specific") { return new CatalogRoute(CatalogRouteKind.SpecificTilePrefab, map, stage, Number(segments[4], id), 0); } } throw Unresolvable(id); } private static EMap ParseMap(string segment, CatalogId id) { if (!Enum.TryParse<EMap>(segment, ignoreCase: true, out var result) || result == EMap.None || !Enum.IsDefined(typeof(EMap), result)) { throw Unresolvable(id); } return result; } private static int Number(string segment, CatalogId id) { if (!int.TryParse(segment, out var result) || result < 0) { throw Unresolvable(id); } return result; } private static ArgumentException Unresolvable(CatalogId id) { return new ArgumentException("catalogId '" + id.Serialize() + "' does not match a known game-asset catalog shape.", "id"); } } public sealed class CellChangeTracker { public const uint PlayerId = uint.MaxValue; private readonly Dictionary<uint, (GridCell Cell, int Level)> _last = new Dictionary<uint, (GridCell, int)>(); public bool Changed(uint id, GridCell cell, int level) { if (_last.TryGetValue(id, out (GridCell, int) value) && value.Item1.Equals(cell) && value.Item2 == level) { return false; } _last[id] = (cell, level); return true; } public void Reset() { _last.Clear(); } } public static class CharacterOverride { public const int TonyMcZoomId = 13; public const int CalciumId = 1; public static string DisplayName(int id) { return id switch { 1 => "Calcium", 13 => "Tony McZoom", _ => $"character {id}", }; } public static bool IsAllowed(int id) { if (id != 1) { return id == 13; } return true; } public static int? TryParseName(string name) { switch (name?.Trim().ToLowerInvariant()) { case "calcium": return 1; case "tony": case "tonymczoom": return 13; default: return null; } } public static string TryApply(Action<int> setSelected, int id = 13) { try { setSelected(id); return null; } catch (Exception ex) { return $"LevelLoader: could not select character {id}, run starts with the default character: {ex.Message}"; } } } public static class DevCharacter { public static int? Resolve(bool devEnabled, string name) { if (!devEnabled) { return null; } if (string.IsNullOrWhiteSpace(name)) { return 13; } return CharacterOverride.TryParseName(name) ?? throw new ArgumentException("'" + name + "' is not an allowed character (calcium, tonymczoom)"); } } public static class CharacterGridOrder { public static IReadOnlyList<int> Pin(IReadOnlyList<int> stockIds) { return new int[2] { 1, 13 }.Where(((IEnumerable<int>)stockIds).Contains<int>).Concat(stockIds.Where((int id) => !CharacterOverride.IsAllowed(id))).ToList(); } } public static class CharacterPolicy { public static IReadOnlyList<int> AllowedIds(IReadOnlyList<string> names) { List<int> list = (names ?? new List<string>()).Select(CharacterOverride.TryParseName).OfType<int>().Distinct() .ToList(); if (list.Count != 0) { return list; } return null; } public static IReadOnlyList<string> UnknownNames(IReadOnlyList<string> names) { return (names ?? new List<string>()).Where((string name) => !CharacterOverride.TryParseName(name).HasValue).ToList(); } public static bool Permits(IReadOnlyList<int> allowedIds, int id) { return allowedIds?.Contains(id) ?? true; } public static string Refusal(IReadOnlyList<int> allowedIds, string levelTitle) { string text = string.Join(" or ", allowedIds.Select(CharacterOverride.DisplayName)); return "Pick " + text + " for " + (levelTitle ?? "this level"); } } public static class CharacterScreenPatch { private readonly record struct ButtonSnapshot(int SiblingIndex, bool CanUse, Color IconColor, bool OverlayActive, string Reason); [HarmonyPatch(typeof(CharacterMenu), "OnEnable")] private static class OnEnablePostfix { private static void Postfix(CharacterMenu __instance) { if (Restricted) { Apply(__instance); } } } [HarmonyPatch(typeof(CharacterMenu), "OnDisable")] private static class OnDisablePostfix { private static void Postfix(CharacterMenu __instance) { MainMenu mainMenu = __instance.mainMenu; GameObject val = ((mainMenu != null) ? mainMenu.tabMaps : null); LevelLoaderPatch.OnMenuDisabled((Object)(object)val != (Object)null && val.activeInHierarchy); } } private const int PlaceholderId = -1; private static ModLogger _logger; private static readonly Dictionary<int, ButtonSnapshot> _stock = new Dictionary<int, ButtonSnapshot>(); private static readonly int[] DefaultAllowedIds = new int[2] { 1, 13 }; private static IReadOnlyList<int> _allowedIds = DefaultAllowedIds; private static ECharacter? _savedCharacter; public static bool Restricted { get; private set; } public static void Install(ModLogger logger) { _logger = logger; } public static void SetRestricted(bool restricted, IReadOnlyList<int> allowedIds = null) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) _allowedIds = allowedIds ?? DefaultAllowedIds; if (restricted && !Restricted) { Preferences obj = SavedPreferences(); _savedCharacter = ((obj != null) ? new ECharacter?(obj.selectedCharacter) : ((ECharacter?)null)); } else if (!restricted && Restricted) { RestoreSavedCharacter(); } Restricted = restricted; foreach (CharacterMenu item in Resources.FindObjectsOfTypeAll<CharacterMenu>()) { Apply(item); } } private static bool IsAllowed(int id) { return CharacterPolicy.Permits(_allowedIds, id); } private static Preferences SavedPreferences() { SaveManager instance = SaveManager.Instance; if (instance == null) { return null; } ConfigSaveFile config = instance.config; if (config == null) { return null; } return config.preferences; } private static void RestoreSavedCharacter() { //IL_0017: 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) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Preferences val = SavedPreferences(); ECharacter? savedCharacter = _savedCharacter; if (savedCharacter.HasValue) { ECharacter valueOrDefault = savedCharacter.GetValueOrDefault(); if (val != null && val.selectedCharacter != valueOrDefault) { val.selectedCharacter = valueOrDefault; SaveManager.Instance.SaveConfig(); _logger?.Msg($"CharacterScreen: saved character restored to {valueOrDefault}"); } } _savedCharacter = null; } private static void Apply(CharacterMenu menu) { if ((Object)(object)menu == (Object)null || (Object)(object)menu.characterGridParent == (Object)null) { return; } Il2CppArrayBase<MyButtonCharacter> componentsInChildren = ((Component)menu.characterGridParent).GetComponentsInChildren<MyButtonCharacter>(true); if (componentsInChildren.Length < 2) { return; } foreach (MyButtonCharacter item in componentsInChildren) { if (!_stock.ContainsKey(((Object)item).GetInstanceID())) { _stock[((Object)item).GetInstanceID()] = Snapshot(item); } } if (Restricted) { Restrict(menu, Il2CppArrayBase<MyButtonCharacter>.op_Implicit(componentsInChildren)); } else { RestoreStock(Il2CppArrayBase<MyButtonCharacter>.op_Implicit(componentsInChildren)); } RebuildNavigation(menu); if (Restricted && ((Component)menu).gameObject.activeInHierarchy) { FocusFirstAllowed(Il2CppArrayBase<MyButtonCharacter>.op_Implicit(componentsInChildren)); } } private static void FocusFirstAllowed(MyButtonCharacter[] buttons) { MyButtonCharacter val = null; foreach (MyButtonCharacter val2 in buttons) { if (IsAllowed(IdOf(val2)) && ((Object)(object)val == (Object)null || ((Component)val2).transform.GetSiblingIndex() < ((Component)val).transform.GetSiblingIndex())) { val = val2; } } if ((Object)(object)val != (Object)null && (Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject(((Component)val).gameObject); } } private static void RebuildNavigation(CharacterMenu menu) { try { List<MyButtonCharacter> value = Traverse.Create((object)menu).Property("characterButtons", (object[])null).GetValue<List<MyButtonCharacter>>(); if (value != null) { List<MyButtonCharacter> list = new List<MyButtonCharacter>(); Enumerator<MyButtonCharacter> enumerator = value.GetEnumerator(); while (enumerator.MoveNext()) { MyButtonCharacter current = enumerator.Current; list.Add(current); } list.Sort((MyButtonCharacter a, MyButtonCharacter b) => ((Component)a).transform.GetSiblingIndex().CompareTo(((Component)b).transform.GetSiblingIndex())); value.Clear(); foreach (MyButtonCharacter item in list) { value.Add(item); } } AccessTools.Method(typeof(CharacterMenu), "SetupButtonNavigation", (Type[])null, (Type[])null).Invoke(menu, null); } catch (Exception ex) { _logger?.Warning("CharacterScreen: could not rebuild navigation: " + ex.Message); } } private static ButtonSnapshot Snapshot(MyButtonCharacter button) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) return new ButtonSnapshot(((Component)button).transform.GetSiblingIndex(), button.canUseCharacter, ((Object)(object)button.i_icon != (Object)null) ? ((Graphic)button.i_icon).color : Color.white, (Object)(object)button.unavailableOverlay != (Object)null && button.unavailableOverlay.activeSelf, button.cantUseCharacterReason); } private static int IdOf(MyButtonCharacter button) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown if (!((Object)(object)button.characterData != (Object)null)) { return -1; } return (int)button.characterData.eCharacter; } private static void Restrict(CharacterMenu menu, MyButtonCharacter[] buttons) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) List<MyButtonCharacter> list = new List<MyButtonCharacter>(buttons); list.Sort((MyButtonCharacter a, MyButtonCharacter b) => _stock[((Object)a).GetInstanceID()].SiblingIndex.CompareTo(_stock[((Object)b).GetInstanceID()].SiblingIndex)); List<int> list2 = list.ConvertAll(IdOf); Dictionary<int, Queue<MyButtonCharacter>> dictionary = new Dictionary<int, Queue<MyButtonCharacter>>(); for (int num = 0; num < list.Count; num++) { if (!dictionary.TryGetValue(list2[num], out var value)) { value = (dictionary[list2[num]] = new Queue<MyButtonCharacter>()); } value.Enqueue(list[num]); } int num2 = 0; foreach (int item in CharacterGridOrder.Pin(list2)) { ((Component)dictionary[item].Dequeue()).transform.SetSiblingIndex(num2++); } foreach (MyButtonCharacter val in buttons) { if (!((Object)(object)val.characterData == (Object)null) && !IsAllowed(IdOf(val))) { val.canUseCharacter = false; val.cantUseCharacterReason = CharacterPolicy.Refusal(_allowedIds, null); if ((Object)(object)val.i_icon != (Object)null) { ((Graphic)val.i_icon).color = Color.black; } if ((Object)(object)val.unavailableOverlay != (Object)null) { val.unavailableOverlay.SetActive(true); } } } _logger?.Msg($"CharacterScreen: restricted to {string.Join(", ", _allowedIds)}, {buttons.Length} buttons"); } private static void RestoreStock(MyButtonCharacter[] buttons) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) foreach (MyButtonCharacter val in buttons) { ButtonSnapshot buttonSnapshot = _stock[((Object)val).GetInstanceID()]; ((Component)val).transform.SetSiblingIndex(buttonSnapshot.SiblingIndex); val.canUseCharacter = buttonSnapshot.CanUse; val.cantUseCharacterReason = buttonSnapshot.Reason; if ((Object)(object)val.i_icon != (Object)null) { ((Graphic)val.i_icon).color = buttonSnapshot.IconColor; } if ((Object)(object)val.unavailableOverlay != (Object)null) { val.unavailableOverlay.SetActive(buttonSnapshot.OverlayActive); } } } } public static class ChestLuck { public static float Roll(IReadOnlyList<float> range, Random random) { if (range != null) { return range[0] + (float)random.NextDouble() * (range[1] - range[0]); } return 0f; } public static float Apply(float luck, float shift) { return luck + shift; } } public static class ChestLuckPatch { [HarmonyPatch(typeof(ItemUtility), "GetRandomChestItem")] private static class GetRandomChestItemPrefix { private static void Prefix(ref float luck) { if (_shift != 0f && CustomLevelState.IsActive) { float num = ChestLuck.Apply(luck, _shift); _logger?.Msg($"ChestLuck: chest loot rolled with luck {luck:F2} shifted to {num:F2}"); luck = num; } } } private static float _shift; private static ModLogger _logger; public static void Install(ModLogger logger) { _logger = logger; } public static void Roll(IReadOnlyList<float> range, ModLogger logger) { _shift = ChestLuck.Roll(range, new Random(Guid.NewGuid().GetHashCode())); if (range != null) { logger.Msg($"ChestLuck: this run's chest luck shift is {_shift:F2} (range {range[0]:F2} to {range[1]:F2})"); } } } public static class ChildHider { public static void Hide(GameObject go, IReadOnlyList<string> names, ModLogger logger) { if (names == null || names.Count == 0) { return; } foreach (Transform componentsInChild in go.GetComponentsInChildren<Transform>(true)) { if (!names.Contains(((Object)componentsInChild).name)) { continue; } foreach (Renderer component in ((Component)componentsInChild).GetComponents<Renderer>()) { component.enabled = false; } foreach (Collider component2 in ((Component)componentsInChild).GetComponents<Collider>()) { component2.enabled = false; } logger?.Msg($"LiveEdit: hid child '{((Object)componentsInChild).name}' of '{((Object)go).name}'"); } } } public static class CollisionRebuild { public static void Replace(ProceduralTileGeneration tileGen, ModLogger logger) { GameObject collider = tileGen.collider; GameObject val = Build(tileGen, logger); if ((Object)(object)val == (Object)null) { logger.Warning("CollisionRebuild: combiner returned nothing; keeping the original collision"); return; } tileGen.collider = val; if ((Object)(object)collider != (Object)null) { Object.Destroy((Object)(object)collider); } } private static GameObject Build(ProceduralTileGeneration tileGen, ModLogger logger) { Dictionary<string, Mesh> dictionary = PrefabColliderMeshes(tileGen); List<GameObject> val = new List<GameObject>(); List<MeshCollider> list = new List<MeshCollider>(); List<GameObject>[] array = new List<GameObject>[3] { tileGen.tiles, tileGen.flatTiles, tileGen.fillTiles }; foreach (List<GameObject> val2 in array) { for (int j = 0; j < val2.Count; j++) { GameObject val3 = val2[j]; if (!((Object)(object)val3 == (Object)null) && val3.activeInHierarchy && dictionary.TryGetValue(StripClone(((Object)val3).name), out var value)) { MeshCollider component = val3.GetComponent<MeshCollider>(); if ((Object)(object)component == (Object)null) { component = val3.AddComponent<MeshCollider>(); component.sharedMesh = value; list.Add(component); } val.Add(val3); } } } GameObject result = MeshColliderCombiner.CombineMeshes(val); foreach (MeshCollider item in list) { Object.Destroy((Object)(object)item); } logger.Msg($"CollisionRebuild: combined {val.Count} pieces ({list.Count} temporary colliders)"); return result; } private static Dictionary<string, Mesh> PrefabColliderMeshes(ProceduralTileGeneration tileGen) { Dictionary<string, Mesh> dictionary = new Dictionary<string, Mesh>(); GameObject[] array = (GameObject[])(object)new GameObject[6] { tileGen.flatTile, tileGen.slopeTile, tileGen.wallFlat, tileGen.wallLeftUp, tileGen.wallLeftDown, tileGen.wallLeftCross }; foreach (GameObject val in array) { MeshCollider val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<MeshCollider>()); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null) { dictionary[((Object)val).name] = val2.sharedMesh; } } return dictionary; } private static string StripClone(string name) { if (!name.EndsWith("(Clone)", StringComparison.Ordinal)) { return name; } return name.Substring(0, name.Length - "(Clone)".Length); } } public readonly record struct ConsoleDevState(bool DevEnabled); public readonly record struct ConsoleToggleState(bool Invulnerable, bool Editor, bool Hud, bool Coordinates); public readonly record struct ConsoleBindResult(HarnessCommand? Command, string Reply, string Error, bool ListHistory = false) { public bool Ok => Error == null; } public sealed class ConsoleVerb { private readonly Func<IReadOnlyList<string>, ConsoleToggleState, IReadOnlyList<string>, ConsoleBindResult> _bind; private Func<int, IReadOnlyList<string>, IEnumerable<string>> _candidates; public string Name { get; } public string Help { get; } public bool Gated { get; } public string Usage { get; } public string[] Aliases { get; private set; } = Array.Empty<string>(); public bool RawError { get; private set; } public ConsoleVerb(string name, string help, bool gated, Func<IReadOnlyList<string>, ConsoleToggleState, IReadOnlyList<string>, ConsoleBindResult> bind, string usage = null) { Name = name; Help = help; Gated = gated; _bind = bind; Usage = usage ?? ("usage: " + name); } public ConsoleVerb WithRawError() { RawError = true; return this; } public ConsoleVerb WithAliases(params string[] aliases) { Aliases = aliases; return this; } public ConsoleVerb WithCandidates(Func<int, IReadOnlyList<string>, IEnumerable<string>> candidates) { _candidates = candidates; return this; } internal IEnumerable<string> Candidates(int argumentIndex, IReadOnlyList<string> levels) { return _candidates?.Invoke(argumentIndex, levels) ?? Enumerable.Empty<string>(); } internal ConsoleBindResult Bind(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> levels) { return _bind(args, toggles, levels); } } public readonly record struct ConsoleCompletion(IReadOnlyList<string> Matches, int Index, string Prefix, IReadOnlyList<string> Lines = null, string Original = "") { public string Text { get { IReadOnlyList<string> matches = Matches; if (matches == null || matches.Count <= 0 || Index < 0 || Index >= matches.Count) { return ""; } return matches[Index]; } } public string Completion { get { if (Text.Length < Prefix.Length) { return ""; } return Text.Substring(Prefix.Length); } } public string Line { get { IReadOnlyList<string> lines = Lines; if (lines == null || lines.Count <= 0 || Index < 0 || Index >= lines.Count) { return Original; } return lines[Index]; } } public ConsoleCompletion Next() { IReadOnlyList<string> matches = Matches; if (matches == null || matches.Count <= 0) { return this; } return this with { Index = (Index + 1) % matches.Count }; } public ConsoleCompletion Prev() { IReadOnlyList<string> matches = Matches; if (matches == null || matches.Count <= 0) { return this; } return this with { Index = (Index - 1 + matches.Count) % matches.Count }; } } public sealed class ConsoleCommandRegistry { private readonly record struct OptionSet(int? Map, int? Stage, int? Tier, int? Seed, int? Size, bool Unseeded, bool Bad) { public static OptionSet Rejected { get; } = new OptionSet(null, null, null, null, null, Unseeded: false, Bad: true); } public const string GatedReply = "requires MEGABONK_DEV"; private const int MinDamageAmount = 1; private const int MaxDamageAmount = 99; private static readonly string[] PerfActions = new string[13] { "report", "status", "start", "reset", "spawn", "timescale", "toggle", "vsync", "render", "physics", "animation", "health", "census" }; private readonly Dictionary<string, ConsoleVerb> _byName = new Dictionary<string, ConsoleVerb>(StringComparer.OrdinalIgnoreCase); private readonly List<ConsoleVerb> _verbs = new List<ConsoleVerb>(); public static ConsoleCommandRegistry Default { get; } = Build(); public IReadOnlyList<ConsoleVerb> Verbs => _verbs; public ConsoleVerb Find(string name) { if (name == null || !_byName.TryGetValue(name, out var value)) { return null; } return value; } public ConsoleBindResult Bind(string line, ConsoleDevState dev, ConsoleToggleState toggles, IReadOnlyList<string> levels = null) { ConsoleTokens consoleTokens = ConsoleCommandTokenizer.Tokenize(line); if (consoleTokens.Tokens == null) { return new ConsoleBindResult(null, null, consoleTokens.Error); } if (consoleTokens.IsBlank) { return new ConsoleBindResult(null, null, null); } ConsoleVerb consoleVerb = Find(consoleTokens.Verb); if (consoleVerb == null) { return new ConsoleBindResult(null, null, UnknownVerb(consoleTokens.Verb)); } if (consoleVerb.Gated && !dev.DevEnabled) { return new ConsoleBindResult(null, null, "requires MEGABONK_DEV"); } if (consoleVerb.Name == "help") { if (consoleTokens.Arguments.Count > 1) { return new ConsoleBindResult(null, null, consoleVerb.Usage); } return new ConsoleBindResult(null, Help((consoleTokens.Arguments.Count == 1) ? consoleTokens.Arguments[0] : null, dev.DevEnabled), null); } ConsoleBindResult result = consoleVerb.Bind(consoleTokens.Arguments, toggles, levels); if (result.Error == "no match") { return new ConsoleBindResult(null, null, consoleVerb.Usage); } if (result.Error != null && !consoleVerb.RawError && !result.Error.StartsWith("usage:", StringComparison.Ordinal)) { return new ConsoleBindResult(null, null, result.Error + "\n" + consoleVerb.Usage); } return result; } public ConsoleCompletion Complete(string line, IReadOnlyList<string> levels = null) { if (line == null) { line = ""; } ConsoleLastWord word = ConsoleCommandTokenizer.LastWord(line); string head = line.Substring(0, word.Start); List<string> list = (from name in Candidates(head, word.WordsBefore, levels) where name.StartsWith(word.Text, StringComparison.OrdinalIgnoreCase) select name).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList(); return new ConsoleCompletion(list, (list.Count == 0) ? (-1) : 0, word.Text, list.Select((string m) => head + QuoteWord(m)).ToList(), line); } private IEnumerable<string> Candidates(string head, int wordsBefore, IReadOnlyList<string> levels) { object obj; if (wordsBefore != 0) { obj = Find(ConsoleCommandTokenizer.Tokenize(head).Verb)?.Candidates(wordsBefore - 1, levels); if (obj == null) { return Enumerable.Empty<string>(); } } else { IEnumerable<string> enumerable = _verbs.SelectMany(VerbNames).OrderBy<string, string>((string name) => name, StringComparer.Ordinal); obj = enumerable; } return (IEnumerable<string>)obj; } private static string QuoteWord(string word) { if (!word.Any(char.IsWhiteSpace)) { return word; } return "\"" + word + "\""; } private string Help(string filter, bool dev) { List<(string Names, string Help)> rows = (from verb in _verbs where (dev || !verb.Gated) && (filter == null || verb.Name.StartsWith(filter, StringComparison.OrdinalIgnoreCase) || verb.Aliases.Any((string a) => a.StartsWith(filter, StringComparison.OrdinalIgnoreCase))) select (Names: verb.Name + ((verb.Aliases.Length != 0) ? (", " + string.Join(", ", verb.Aliases)) : ""), Help: verb.Help)).ToList(); if (rows.Count != 0) { return string.Join("\n", rows.Select(((string Names, string Help) row) => row.Names.PadRight(rows.Max(((string Names, string Help) r) => r.Names.Length) + 2) + row.Help)); } return "no verb matches " + filter; } private string UnknownVerb(string typed) { List<string> list = Suggest(typed); string text = "unknown verb '" + typed + "'"; if (list.Count != 0) { return text + "; did you mean " + string.Join(", ", list) + "?"; } return text; } private static IEnumerable<string> VerbNames(ConsoleVerb verb) { yield return verb.Name; string[] aliases = verb.Aliases; for (int i = 0; i < aliases.Length; i++) { yield return aliases[i]; } } private List<string> Suggest(string typed) { string lower = typed.ToLowerInvariant(); int threshold = Math.Max(2, typed.Length / 2); return (from row in (from name in _verbs.SelectMany(VerbNames) select (name: name, distance: Distance(lower, name.ToLowerInvariant())) into row where row.distance <= threshold || row.name.StartsWith(typed, StringComparison.OrdinalIgnoreCase) orderby row.distance select row).ThenBy<(string, int), string>(((string name, int distance) row) => row.name, StringComparer.Ordinal) select row.name).Distinct<string>(StringComparer.OrdinalIgnoreCase).Take(3).ToList(); } private static int Distance(string a, string b) { int[] array = new int[b.Length + 1]; int[] array2 = new int[b.Length + 1]; for (int i = 0; i <= b.Length; i++) { array[i] = i; } for (int j = 1; j <= a.Length; j++) { array2[0] = j; for (int k = 1; k <= b.Length; k++) { int num = ((a[j - 1] != b[k - 1]) ? 1 : 0); array2[k] = Math.Min(Math.Min(array2[k - 1] + 1, array[k] + 1), array[k - 1] + num); } int[] array3 = array2; array2 = array; array = array3; } return array[b.Length]; } private ConsoleVerb Add(ConsoleVerb verb) { _verbs.Add(verb); _byName[verb.Name] = verb; string[] aliases = verb.Aliases; foreach (string key in aliases) { _byName[key] = verb; } return verb; } private static ConsoleCommandRegistry Build() { ConsoleCommandRegistry consoleCommandRegistry = new ConsoleCommandRegistry(); consoleCommandRegistry.Add(new ConsoleVerb("help", "list verbs, aliases and one line of help", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count > 1) ? NoMatch() : new ConsoleBindResult(null, null, null)).WithAliases("?")); consoleCommandRegistry.Add(new ConsoleVerb("clear", "clear the console scrollback", gated: false, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => NoCommand()).WithAliases("cls")); consoleCommandRegistry.Add(new ConsoleVerb("history", "list the lines typed in earlier sessions and this one", gated: false, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => new ConsoleBindResult(null, "", null, ListHistory: true))); consoleCommandRegistry.Add(new ConsoleVerb("state", "read the game's current state", gated: false, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.State))); float[] values; consoleCommandRegistry.Add(new ConsoleVerb("player.teleport", "move the player to a world position", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { if (args.Count != 3 || !Floats(args, out values)) { return NoMatch(); } TeleportArgs teleport = new TeleportArgs { Position = values }; return Command(new HarnessCommand(HarnessCommandKind.Teleport, null, default(CameraPose), Enabled: false, null, null, teleport)); }, "usage: player.teleport x y z").WithAliases("tp")); consoleCommandRegistry.Add(new ConsoleVerb("player.teleport_cell", "move the player to a grid cell", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { if (args.Count != 2 || !Ints(args, out values)) { return NoMatch(); } TeleportArgs teleport = new TeleportArgs { Cell = values }; return Command(new HarnessCommand(HarnessCommandKind.Teleport, null, default(CameraPose), Enabled: false, null, null, teleport)); })); consoleCommandRegistry.Add(new ConsoleVerb("player.god", "make the player survive damage", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> _) { bool? flag = Flag(args, toggles.Invulnerable); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(valueOrDefault ? HarnessCommandKind.Invulnerable : HarnessCommandKind.Vulnerable, valueOrDefault); }).WithAliases("tgm")); consoleCommandRegistry.Add(new ConsoleVerb("player.kill", "end the run at once", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.Kill))); consoleCommandRegistry.Add(new ConsoleVerb("player.damage", "apply 1-99 damage, fatal with 'lethal'", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { int count = args.Count; bool flag = (uint)(count - 1) <= 1u; if (flag && Int(args[0], 1, 99, out var parsed)) { bool? flag2 = Nonlethal(args); if (flag2.HasValue) { bool valueOrDefault = flag2 == true; DamageArgs damage = new DamageArgs { Amount = parsed, Nonlethal = valueOrDefault }; return Command(new HarnessCommand(HarnessCommandKind.Damage, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, damage)); } } return NoMatch(); })); consoleCommandRegistry.Add(new ConsoleVerb("player.add_item", "read or set an item amount", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { int parsed = 0; int count = args.Count; bool flag = (uint)(count - 1) <= 1u; if (!flag || args[0].Length <= 0 || (args.Count != 1 && !Int(args[1], 0, 999, out parsed))) { return NoMatch(); } ItemArgs item = new ItemArgs { Name = args[0], Amount = ((args.Count == 2) ? new int?(parsed) : ((int?)null)) }; return Command(new HarnessCommand(HarnessCommandKind.Item, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), item)); })); consoleCommandRegistry.Add(new ConsoleVerb("player.fall_damage", "read the live fall-damage inputs", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.FallDamage))); consoleCommandRegistry.Add(new ConsoleVerb("enemies.kill", "kill nearest, all or bosses", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { string text = ((args.Count == 0) ? "all" : args[0].ToLowerInvariant()); if (Array.IndexOf(EnemyKillTargets.Names, text) < 0) { return NoMatch(); } string killTarget = text; return Command(new HarnessCommand(HarnessCommandKind.KillEnemies, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: false, null, null, killTarget)); }).WithAliases("killall")); consoleCommandRegistry.Add(new ConsoleVerb("enemies.spawns", "allow or stop new enemy spawns", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { bool? flag = Flag(args, current: true); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Spawns, valueOrDefault); })); consoleCommandRegistry.Add(new ConsoleVerb("run.freeze", "stop gameplay", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.Freeze))); consoleCommandRegistry.Add(new ConsoleVerb("run.resume", "start gameplay again", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.Resume))); consoleCommandRegistry.Add(new ConsoleVerb("run.restart", "run the death screen's Retry", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.RestartRun))); consoleCommandRegistry.Add(new ConsoleVerb("run.dismiss_levelup", "pick an upgrade in the level-up dialog", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { int parsed = 0; if (args.Count > 1 || (args.Count != 0 && !Int(args[0], 0, int.MaxValue, out parsed))) { return NoMatch(); } int choice = ((args.Count == 1) ? parsed : 0); return Command(new HarnessCommand(HarnessCommandKind.DismissLevelUp, null, default(CameraPose), Enabled: false, null, null, null, choice)); })); consoleCommandRegistry.Add(new ConsoleVerb("run.dismiss_offers", "close, pick or skip the open reward window", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { switch (args.Count) { case 0: return Command(new HarnessCommand(HarnessCommandKind.DismissOffers, null)); case 1: { if (args[0] == "skip") { return Command(new HarnessCommand(HarnessCommandKind.DismissOffers, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: true)); } if (Int(args[0], 0, int.MaxValue, out var parsed)) { int? offer = parsed; return Command(new HarnessCommand(HarnessCommandKind.DismissOffers, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, offer)); } break; } } return NoMatch(); })); consoleCommandRegistry.Add(new ConsoleVerb("run.interact", "activate the nearest interactable, or one type", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { if (args.Count > 1 || (args.Count != 0 && args[0].Length <= 0)) { return NoMatch(); } InteractArgs interact = new InteractArgs { Type = ((args.Count == 1) ? args[0] : null) }; return Command(new HarnessCommand(HarnessCommandKind.Interact, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: false, interact)); })); consoleCommandRegistry.Add(new ConsoleVerb("run.press_death_confirm", "press the death screen's confirm", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.PressDeathConfirm))); consoleCommandRegistry.Add(new ConsoleVerb("run.press_summary_restart", "press the run summary's restart", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.PressSummaryRestart))); consoleCommandRegistry.Add(new ConsoleVerb("level.list", "list the saved custom-level files", gated: false, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.ListLevels))); consoleCommandRegistry.Add(new ConsoleVerb("level.load", "load a level by path or title, with map/stage/tier/seed/noseed", gated: true, (IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> levels) => LoadLevel(args, toggles, levels)).WithAliases("coc").WithRawError().WithCandidates(LevelTitles)); consoleCommandRegistry.Add(new ConsoleVerb("level.save", "save the editor's level, optionally under a name", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count > 1 || (args.Count != 0 && args[0].Trim().Length <= 0)) ? NoMatch() : Command(new HarnessCommand(HarnessCommandKind.SaveLevel, (args.Count == 1) ? args[0] : null)))); consoleCommandRegistry.Add(new ConsoleVerb("level.new", "write a blank level and edit it, with map/stage/tier/size", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => NewLevel(args))); consoleCommandRegistry.Add(new ConsoleVerb("editor", "enter or leave editor mode", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> _) { bool? flag = Flag(args, toggles.Editor); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Editor, valueOrDefault); }).WithAliases("tfc")); consoleCommandRegistry.Add(new ConsoleVerb("camera.set", "hold the camera at a pose", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count != 6 || !Floats(args, out values)) ? NoMatch() : Command(new HarnessCommand(HarnessCommandKind.Camera, null, new CameraPose(values[0], values[1], values[2], values[3], values[4], values[5]))))); consoleCommandRegistry.Add(new ConsoleVerb("camera.clear", "return the camera to the game", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.CameraClear))); consoleCommandRegistry.Add(new ConsoleVerb("ui.hud", "show or hide the stock HUD", gated: false, delegate(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> _) { bool? flag = Flag(args, toggles.Hud); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Hud, valueOrDefault); }).WithAliases("tm")); consoleCommandRegistry.Add(new ConsoleVerb("ui.coordinates", "show or hide coordinates", gated: false, delegate(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> _) { bool? flag = Flag(args, toggles.Coordinates); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Coordinates, valueOrDefault); })); string[] perfActions = PerfActions; foreach (string action in perfActions) { consoleCommandRegistry.Add(new ConsoleVerb("perf." + action, PerfHelp(action), gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => Perf(action, args), PerfUsage(action))); } consoleCommandRegistry.Add(new ConsoleVerb("time_scale", "hold MyTime.timeScale, or release it with no value", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => Perf("timescale", args), "usage: time_scale [value]")); consoleCommandRegistry.Add(new ConsoleVerb("debug.screenshot", "save the rendered frame as a PNG", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count != 1 || args[0].Trim().Length <= 0) ? NoMatch() : Command(new HarnessCommand(HarnessCommandKind.Screenshot, args[0])))); consoleCommandRegistry.Add(new ConsoleVerb("debug.query_objects", "list loaded objects of a type with chosen fields", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { if (args.Count < 1 || args[0].Length <= 0 || !args.Skip(1).All((string f) => f.Length > 0)) { return NoMatch(); } QueryArgs query = new QueryArgs { TypeName = args[0], Fields = args.Skip(1).ToArray() }; return Command(new HarnessCommand(HarnessCommandKind.QueryObjects, null, default(CameraPose), Enabled: false, null, null, null, 0, query)); })); consoleCommandRegistry.Add(new ConsoleVerb("debug.material_dump", "dump the materials under the named objects", gated: true, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count > 1 || (args.Count != 0 && args[0].Trim().Length <= 0)) ? NoMatch() : Command(new HarnessCommand(HarnessCommandKind.MaterialDump, (args.Count == 1) ? args[0] : null)))); consoleCommandRegistry.Add(new ConsoleVerb("debug.shader_report", "list the shaders the game ships and uses", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.ShaderReport))); consoleCommandRegistry.Add(new ConsoleVerb("debug.heartbeat", "start or stop the kill-floor heartbeat", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { bool? flag = Flag(args, current: true); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Heartbeat, valueOrDefault); })); consoleCommandRegistry.Add(new ConsoleVerb("debug.cells", "start or stop the cell-change log", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { bool? flag = Flag(args, current: true); if (!flag.HasValue) { return NoMatch(); } bool valueOrDefault = flag == true; return Enabled(HarnessCommandKind.Cells, valueOrDefault); })); consoleCommandRegistry.Add(new ConsoleVerb("debug.ui_tree", "list the editor widgets, or the one at a pixel", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { switch (args.Count) { case 0: { InputArgs input = new InputArgs { Action = "ui-tree" }; return Command(new HarnessCommand(HarnessCommandKind.UiTree, null, default(CameraPose), Enabled: false, null, input)); } case 2: { if (Float(args[0], out var parsed) && Float(args[1], out var parsed2)) { InputArgs input = new InputArgs { Action = "ui-tree", X = parsed, Y = parsed2 }; return Command(new HarnessCommand(HarnessCommandKind.UiTree, null, default(CameraPose), Enabled: false, null, input)); } break; } } return NoMatch(); })); consoleCommandRegistry.Add(new ConsoleVerb("debug.click_widget", "click the named editor widget", gated: true, delegate(IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) { if (args.Count != 1 || args[0].Length <= 0) { return NoMatch(); } InputArgs input = new InputArgs { Action = "click-widget", Text = args[0] }; return Command(new HarnessCommand(HarnessCommandKind.ClickWidget, null, default(CameraPose), Enabled: false, null, input)); })); consoleCommandRegistry.Add(new ConsoleVerb("app.quit", "quit the game", gated: true, (IReadOnlyList<string> _, ConsoleToggleState _, IReadOnlyList<string> _) => Command(HarnessCommandKind.Quit)).WithAliases("qqq")); consoleCommandRegistry.Add(new ConsoleVerb("music.play", "resume paused music, or play track n", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => (args.Count != 0) ? MusicTrack(args) : MusicTransport(args, "play"), "usage: music.play [n]")); consoleCommandRegistry.Add(new ConsoleVerb("music.pause", "pause the current music", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTransport(args, "pause"))); consoleCommandRegistry.Add(new ConsoleVerb("music.next", "go to the next track", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTransport(args, "next"))); consoleCommandRegistry.Add(new ConsoleVerb("music.prev", "go to the previous track", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTransport(args, "prev"))); consoleCommandRegistry.Add(new ConsoleVerb("music.track", "jump to track n", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTrack(args), "usage: music.track n")); consoleCommandRegistry.Add(new ConsoleVerb("music.list", "list the tracks, marking the current one", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTransport(args, "list"))); consoleCommandRegistry.Add(new ConsoleVerb("music.now", "show the current track", gated: false, (IReadOnlyList<string> args, ConsoleToggleState _, IReadOnlyList<string> _) => MusicTransport(args, "now"))); return consoleCommandRegistry; } private static ConsoleBindResult MusicTrack(IReadOnlyList<string> args) { if (args.Count != 1 || !Int(args[0], 1, int.MaxValue, out var parsed)) { return NoMatch(); } MusicArgs music = new MusicArgs { Action = "track", Track = parsed }; return Command(new HarnessCommand(HarnessCommandKind.Music, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: false, null, null, null, music)); } private static ConsoleBindResult MusicTransport(IReadOnlyList<string> args, string action) { if (args.Count != 0) { return NoMatch(); } MusicArgs music = new MusicArgs { Action = action }; return Command(new HarnessCommand(HarnessCommandKind.Music, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: false, null, null, null, music)); } private static ConsoleBindResult NoCommand() { return new ConsoleBindResult(null, "", null); } private static ConsoleBindResult NoMatch() { return new ConsoleBindResult(null, null, "no match"); } private static ConsoleBindResult Command(HarnessCommandKind kind) { return new ConsoleBindResult(new HarnessCommand(kind, null), null, null); } private static ConsoleBindResult Command(HarnessCommand command) { return new ConsoleBindResult(command, null, null); } private static ConsoleBindResult Enabled(HarnessCommandKind kind, bool enabled) { bool enabled2 = enabled; return new ConsoleBindResult(new HarnessCommand(kind, null, default(CameraPose), enabled2), null, null); } private static string PerfHelp(string action) { return action switch { "report" => "frame percentiles for the last window", "status" => "the live profiler toggles", "start" => "clear the window and start measuring", "reset" => "restore every profiler setting", "spawn" => "add enemies around the player", "timescale" => "hold or release MyTime.timeScale", "toggle" => "switch one tick or patch probe", "vsync" => "lift or restore the vsync cap", "render" => "hide or show enemy renderers", "physics" => "freeze or unfreeze enemy rigidbodies", "animation" => "stop or resume enemy animation", "health" => "park the player's hit points", "census" => "count components by type", _ => "frame profiler", }; } private static string PerfUsage(string action) { switch (action) { case "toggle": return "usage: perf.toggle <target> <on|off>"; case "render": case "vsync": case "animation": case "physics": return "usage: perf." + action + " <on|off>"; case "spawn": return $"usage: perf.spawn <1-{300}>"; case "timescale": return "usage: perf.timescale [value]"; case "health": return "usage: perf.health [hp]"; default: return "usage: perf." + action; } } private static ConsoleBindResult Perf(string action, IReadOnlyList<string> args) { switch (action) { case "spawn": { if (args.Count != 1 || !Int(args[0], 1, 300, out var parsed3)) { return NoMatch(); } PerfArgs perf = new PerfArgs { Action = action, Count = parsed3 }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } case "timescale": { float parsed = 0f; if (args.Count > 1 || (args.Count != 0 && (!Float(args[0], out parsed) || !PerfLimits.ValidTimeScale(parsed)))) { return NoMatch(); } PerfArgs perf = new PerfArgs { Action = action, Value = ((args.Count == 1) ? new float?(parsed) : ((float?)null)) }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } case "toggle": if (args.Count == 2 && args[0].Length > 0) { bool? flag = OnOff(args[1]); if (flag.HasValue) { bool valueOrDefault = flag == true; PerfArgs perf = new PerfArgs { Action = action, Target = args[0], Enabled = valueOrDefault }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } } return NoMatch(); case "vsync": case "animation": case "render": case "physics": if (args.Count == 1) { bool? flag = OnOff(args[0]); if (flag.HasValue) { bool valueOrDefault2 = flag == true; PerfArgs perf = new PerfArgs { Action = action, Enabled = valueOrDefault2 }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } } return NoMatch(); case "health": { int parsed2 = 0; if (args.Count > 1 || (args.Count != 0 && !Int(args[0], 1, 100000000, out parsed2))) { return NoMatch(); } PerfArgs perf = new PerfArgs { Action = action, Hp = ((args.Count == 1) ? new int?(parsed2) : ((int?)null)) }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } default: { if (args.Count != 0) { return NoMatch(); } PerfArgs perf = new PerfArgs { Action = action }; return Command(new HarnessCommand(HarnessCommandKind.Perf, null, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, perf)); } } } private static ConsoleBindResult LoadLevel(IReadOnlyList<string> args, ConsoleToggleState toggles, IReadOnlyList<string> levels) { if (args.Count == 0 || string.IsNullOrWhiteSpace(args[0])) { return NoMatch(); } string error; string text = ResolveLevelTarget(args[0], levels, out error); if (text == null) { return new ConsoleBindResult(null, null, error); } OptionSet optionSet = ParseOverrides(args.Skip(1).ToArray(), allowSize: false); if (optionSet.Bad) { return NoMatch(); } bool flag = !text.Contains('/') && !text.Contains('\\'); bool flag2 = optionSet.Map.HasValue || optionSet.Stage.HasValue || optionSet.Tier.HasValue || optionSet.Seed.HasValue || optionSet.Unseeded; if (toggles.Editor && flag && !flag2) { return Command(new HarnessCommand(HarnessCommandKind.EditorLoad, text)); } LoadOverrides overrides = new LoadOverrides(optionSet.Map, optionSet.Stage, optionSet.Tier, optionSet.Seed, null, optionSet.Unseeded); return Command(new HarnessCommand(HarnessCommandKind.LoadLevel, text, default(CameraPose), Enabled: false, null, null, null, 0, null, overrides)); } private static ConsoleBindResult NewLevel(IReadOnlyList<string> args) { string text = ((args.Count > 0 && args[0].Trim().Length > 0) ? args[0] : null); OptionSet optionSet = ParseOverrides(args.Skip((text != null) ? 1 : 0).ToArray(), allowSize: true); if (!optionSet.Bad) { NewLevelArgs? newLevel = new NewLevelArgs(optionSet.Map ?? 1, optionSet.Stage.GetValueOrDefault(), optionSet.Tier.GetValueOrDefault(), optionSet.Size ?? 7); return Command(new HarnessCommand(HarnessCommandKind.NewLevel, text, default(CameraPose), Enabled: false, null, null, null, 0, null, default(LoadOverrides), null, null, null, null, null, Skip: false, null, newLevel)); } return NoMatch(); } private static OptionSet ParseOverrides(IReadOnlyList<string> args, bool allowSize) { int? map = null; int? stage = null; int? tier = null; int? seed = null; int? size = null; bool unseeded = false; for (int i = 0; i < args.Count; i++) { bool flag = i == args.Count - 1; if (args[i] == "noseed" && flag) { unseeded = true; continue; } if (flag) { return OptionSet.Rejected; } bool flag2 = true; switch (args[i]) { case "map": { flag2 = Int(args[i + 1], 0, int.MaxValue, out var parsed4) && ValidMap(parsed4) && Set(parsed4, delegate(int v) { map = v; }); break; } case "stage": { flag2 = Int(args[i + 1], 0, int.MaxValue, out var parsed3) && Set(parsed3, delegate(int v) { stage = v; }); break; } case "tier": { flag2 = Int(args[i + 1], 0, int.MaxValue, out var parsed5) && Set(parsed5, delegate(int v) { tier = v; }); break; } case "seed": { flag2 = Int(args[i + 1], int.MinValue, int.MaxValue, out var parsed2) && Set(parsed2, delegate(int v) { seed = v; }); break; } case "size": if (allowSize) { flag2 = Int(args[i + 1], 3, int.MaxValue, out var parsed) && Set(parsed, delegate(int v) { size = v; }); break; } goto default; default: flag2 = false; break; } if (!flag2) { return OptionSet.Rejected; } i++; } return new OptionSet(map, stage, tier, seed, size, unseeded, Bad: false); } private static bool Set<T>(T value, Action<T> assign) { assign(value); return true; } private static bool ValidMap(int value) { return Enum.GetValues<EMap>().Any((EMap m) => m != EMap.None && m == (EMap)value); } private static string ResolveLevelTarget(string target, IReadOnlyList<string> levels, out string error) { error = null; bool flag = target.EndsWith(".json", StringComparison.OrdinalIgnoreCase); if (target.Contains('/') || target.Contains('\\')) { return target; } string fileName = (flag ? target : (target + ".mblevel.json")); if (levels == null || levels.Count == 0) { return fileName; } string wanted = Normalize(target); List<string> list = levels.Where((string l) => Normalize(LevelStem(l)) == wanted).ToList(); if (list.Count == 1) { return list[0]; } if (list.Count > 1) { error = "'" + target + "' is ambiguous: " + string.Join(", ", list); return null; } string text = levels.FirstOrDefault((string l) => string.Equals(l, fileName, StringComparison.OrdinalIgnoreCase)); if (text != null) { return text; } error = "no level named '" + target + "'; run level.list"; return null; } private static IEnumerable<string> LevelTitles(int argumentIndex, IReadOnlyList<string> levels) { if (argumentIndex != 0 || levels == null) { return Enumerable.Empty<string>(); } return levels.Select(LevelStem); } private static string Normalize(string value) { return new string((value ?? "").Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); } private static string LevelStem(string fileName) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); if (!fileNameWithoutExtension.EndsWith(".mblevel", StringComparison.OrdinalIgnoreCase)) { return fileNameWithoutExtension; } return fileNameWithoutExtension.Substring(0, fileNameWithoutExtension.Length - ".mblevel".Length); } private static bool? Flag(IReadOnlyList<string> args, bool current) { if (args.Count != 1) { if (args.Count != 0) { return null; } return !current; } return OnOff(args[0]); } private static bool? OnOff(string value) { if (!string.Equals(value, "on", StringComparison.OrdinalIgnoreCase)) { if (!string.Equals(value, "off", StringComparison.OrdinalIgnoreCase)) { return null; } return false; } return true; } private static bool? Nonlethal(IReadOnlyList<string> args) { switch (args.Count) { case 1: return true; case 2: if (string.Equals(args[1], "lethal", StringComparison.OrdinalIgnoreCase)) { return false; } if (string.Equals(args[1], "nonlethal", StringComparison.OrdinalIgnoreCase)) { return true; } return OnOff(args[1]); default: return null; } } private static bool Int(string value, int min, int max, out int parsed) { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out parsed) && parsed >= min) { return parsed <= max; } return false; } private static bool Ints(IReadOnlyList<string> args, out int[] values) { values = null; if (args.Count != 2) { return false; } values = new int[2]; if (Int(args[0], int.MinValue, int.MaxValue, out values[0])) { return Int(args[1], int.MinValue, int.MaxValue, out values[1]); } return false; } private static bool Float(string va
BepInEx/plugins/MegabonkLevels/NLayer.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using NLayer.Decoder; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mark Heath, Andrew Ward")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Fully Managed MPEG 1 & 2 Decoder for Layers 1, 2, & 3")] [assembly: AssemblyFileVersion("1.16.0.0")] [assembly: AssemblyInformationalVersion("1.16.0+c88b0d8abfa15c1e506106931ea8410170dc6326")] [assembly: AssemblyProduct("NLayer")] [assembly: AssemblyTitle("NLayer")] [assembly: AssemblyVersion("1.16.0.0")] namespace NLayer { public enum MpegVersion { Unknown = 0, Version1 = 10, Version2 = 20, Version25 = 25 } public enum MpegLayer { Unknown, LayerI, LayerII, LayerIII } public enum MpegChannelMode { Stereo, JointStereo, DualChannel, Mono } public enum StereoMode { Both, LeftOnly, RightOnly, DownmixToMono } public interface IMpegFrame { int SampleRate { get; } int SampleRateIndex { get; } int FrameLength { get; } int BitRate { get; } MpegVersion Version { get; } MpegLayer Layer { get; } MpegChannelMode ChannelMode { get; } int ChannelModeExtension { get; } int SampleCount { get; } int BitRateIndex { get; } bool IsCopyrighted { get; } bool HasCrc { get; } bool IsCorrupted { get; } void Reset(); int ReadBits(int bitCount); } public class MpegFile : IDisposable { private Stream _stream; private bool _closeStream; private bool _eofFound; private MpegStreamReader _reader; private MpegFrameDecoder _decoder; private object _seekLock = new object(); private long _position; private float[] _readBuf = new float[2304]; private int _readBufLen; private int _readBufOfs; public int SampleRate => _reader.SampleRate; public int Channels => _reader.Channels; public bool CanSeek => _reader.CanSeek; public long Length => _reader.SampleCount * _reader.Channels * 4; public TimeSpan Duration { get { long sampleCount = _reader.SampleCount; if (sampleCount == -1) { return TimeSpan.Zero; } return TimeSpan.FromSeconds((double)sampleCount / (double)_reader.SampleRate); } } public long Position { get { return _position; } set { if (!_reader.CanSeek) { throw new InvalidOperationException("Cannot Seek!"); } if (value < 0) { throw new ArgumentOutOfRangeException("value"); } long num = value / 4 / _reader.Channels; int num2 = 0; if (num >= _reader.FirstFrameSampleCount) { num2 = _reader.FirstFrameSampleCount; num -= num2; } lock (_seekLock) { long num3 = _reader.SeekTo(num); if (num3 == -1) { throw new ArgumentOutOfRangeException("value"); } _decoder.Reset(); if (num2 != 0) { _decoder.DecodeFrame(_reader.NextFrame(), _readBuf, 0); num3 += num2; } _position = num3 * 4 * _reader.Channels; _eofFound = false; _readBufOfs = (_readBufLen = 0); } } } public TimeSpan Time { get { return TimeSpan.FromSeconds((double)_position / 4.0 / (double)_reader.Channels / (double)_reader.SampleRate); } set { Position = (long)(value.TotalSeconds * (double)_reader.SampleRate * (double)_reader.Channels * 4.0); } } public StereoMode StereoMode { get { return _decoder.StereoMode; } set { _decoder.StereoMode = value; } } public MpegFile(string fileName) { Init(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), closeStream: true); } public MpegFile(Stream stream) { Init(stream, closeStream: false); } private void Init(Stream stream, bool closeStream) { _stream = stream; _closeStream = closeStream; _reader = new MpegStreamReader(_stream); _decoder = new MpegFrameDecoder(); } public void Dispose() { if (_closeStream) { _stream.Dispose(); _closeStream = false; } } public void SetEQ(float[] eq) { _decoder.SetEQ(eq); } public int ReadSamples(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } count -= count % 4; return ReadSamplesImpl(buffer, index, count, 32); } public int ReadSamples(float[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index * 4, count * 4, 32) / 4; } public int ReadSamplesInt16(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length * 2) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index, count, 16) * 2 / 4; } public int ReadSamplesInt8(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length * 4) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index, count, 8) / 4; } private int ReadSamplesImpl(Array buffer, int index, int count, int bitDepth) { int num = 0; lock (_seekLock) { while (count > 0) { if (_readBufLen > _readBufOfs) { int num2 = _readBufLen - _readBufOfs; if (num2 > count) { num2 = count; } if (bitDepth == 32) { Buffer.BlockCopy(_readBuf, _readBufOfs, buffer, index, num2); } else { for (int i = 0; i < num2 / 4; i++) { switch (bitDepth) { case 8: buffer.SetValue((byte)Math.Round(127.5f * _readBuf[_readBufOfs / 4 + i] + 127.5f), index / 4 + i); break; case 16: { int num3 = (int)Math.Round(32767.5f * _readBuf[_readBufOfs / 4 + i] - 0.5f); if (num3 < 0) { num3 += 65536; } buffer.SetValue((byte)(num3 % 256), 2 * (index / 4 + i)); buffer.SetValue((byte)(num3 / 256), 2 * (index / 4 + i) + 1); break; } } } } num += num2; count -= num2; index += num2; _position += num2; _readBufOfs += num2; if (_readBufOfs == _readBufLen) { _readBufLen = 0; } } if (_readBufLen != 0) { continue; } if (_eofFound) { break; } MpegFrame mpegFrame = _reader.NextFrame(); if (mpegFrame == null) { _eofFound = true; break; } try { _readBufLen = _decoder.DecodeFrame(mpegFrame, _readBuf, 0) * 4; _readBufOfs = 0; } catch (InvalidDataException) { _decoder.Reset(); _readBufOfs = (_readBufLen = 0); } catch (EndOfStreamException) { _eofFound = true; break; } finally { mpegFrame.ClearBuffer(); } } } return num; } } public class MpegFrameDecoder { private LayerIDecoder _layerIDecoder; private LayerIIDecoder _layerIIDecoder; private LayerIIIDecoder _layerIIIDecoder; private float[] _eqFactors; private float[] _ch0; private float[] _ch1; public StereoMode StereoMode { get; set; } public MpegFrameDecoder() { _ch0 = new float[1152]; _ch1 = new float[1152]; } public void SetEQ(float[] eq) { if (eq != null) { float[] array = new float[32]; for (int i = 0; i < eq.Length; i++) { array[i] = (float)Math.Pow(2.0, eq[i] / 6f); } _eqFactors = array; } else { _eqFactors = null; } } public int DecodeFrame(IMpegFrame frame, byte[] dest, int destOffset) { if (frame == null) { throw new ArgumentNullException("frame"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (destOffset % 4 != 0) { throw new ArgumentException("Must be an even multiple of 4", "destOffset"); } if ((dest.Length - destOffset) / 4 < ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) * frame.SampleCount) { throw new ArgumentException("Buffer not large enough! Must be big enough to hold the frame's entire output. This is up to 9,216 bytes.", "dest"); } return DecodeFrameImpl(frame, dest, destOffset / 4) * 4; } public int DecodeFrame(IMpegFrame frame, float[] dest, int destOffset) { if (frame == null) { throw new ArgumentNullException("frame"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (dest.Length - destOffset < ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) * frame.SampleCount) { throw new ArgumentException("Buffer not large enough! Must be big enough to hold the frame's entire output. This is up to 2,304 elements.", "dest"); } return DecodeFrameImpl(frame, dest, destOffset); } private int DecodeFrameImpl(IMpegFrame frame, Array dest, int destOffset) { frame.Reset(); LayerDecoderBase layerDecoderBase = null; switch (frame.Layer) { case MpegLayer.LayerI: if (_layerIDecoder == null) { _layerIDecoder = new LayerIDecoder(); } layerDecoderBase = _layerIDecoder; break; case MpegLayer.LayerII: if (_layerIIDecoder == null) { _layerIIDecoder = new LayerIIDecoder(); } layerDecoderBase = _layerIIDecoder; break; case MpegLayer.LayerIII: if (_layerIIIDecoder == null) { _layerIIIDecoder = new LayerIIIDecoder(); } layerDecoderBase = _layerIIIDecoder; break; } if (layerDecoderBase != null) { layerDecoderBase.SetEQ(_eqFactors); layerDecoderBase.StereoMode = StereoMode; int num = layerDecoderBase.DecodeFrame(frame, _ch0, _ch1); if (frame.ChannelMode == MpegChannelMode.Mono) { Buffer.BlockCopy(_ch0, 0, dest, destOffset * 4, num * 4); } else { for (int i = 0; i < num; i++) { Buffer.BlockCopy(_ch0, i * 4, dest, destOffset * 4, 4); destOffset++; Buffer.BlockCopy(_ch1, i * 4, dest, destOffset * 4, 4); destOffset++; } num *= 2; } return num; } return 0; } public void Reset() { if (_layerIDecoder != null) { _layerIDecoder.ResetForSeek(); } if (_layerIIDecoder != null) { _layerIIDecoder.ResetForSeek(); } if (_layerIIIDecoder != null) { _layerIIIDecoder.ResetForSeek(); } } } } namespace NLayer.Decoder { internal class BitReservoir { private byte[] _buf = new byte[8192]; private int _start; private int _end = -1; private int _bitsLeft; private long _bitsRead; public int BitsAvailable { get { if (_bitsLeft > 0) { return (_end + _buf.Length - _start) % _buf.Length * 8 + _bitsLeft; } return 0; } } public long BitsRead => _bitsRead; private static int GetSlots(IMpegFrame frame) { int num = frame.FrameLength - 4; if (frame.HasCrc) { num -= 2; } if (frame.Version == MpegVersion.Version1 && frame.ChannelMode != MpegChannelMode.Mono) { return num - 32; } if (frame.Version > MpegVersion.Version1 && frame.ChannelMode == MpegChannelMode.Mono) { return num - 9; } return num - 17; } public bool AddBits(IMpegFrame frame, int overlap) { int end = _end; int num = GetSlots(frame); while (--num >= 0) { int num2 = frame.ReadBits(8); if (num2 == -1) { throw new InvalidDataException("Frame did not have enough bytes!"); } _buf[++_end] = (byte)num2; if (_end == _buf.Length - 1) { _end = -1; } } _bitsLeft = 8; if (end == -1) { return overlap == 0; } if ((end + 1 - _start + _buf.Length) % _buf.Length >= overlap) { _start = (end + 1 - overlap + _buf.Length) % _buf.Length; return true; } _start = end + overlap; return false; } public int GetBits(int count) { int readCount; int result = TryPeekBits(count, out readCount); if (readCount < count) { throw new InvalidDataException("Reservoir did not have enough bytes!"); } SkipBits(count); return result; } public int Get1Bit() { if (_bitsLeft == 0) { throw new InvalidDataException("Reservoir did not have enough bytes!"); } _bitsLeft--; _bitsRead++; int result = (_buf[_start] >> _bitsLeft) & 1; if (_bitsLeft == 0 && (_start = (_start + 1) % _buf.Length) != _end + 1) { _bitsLeft = 8; } return result; } public int TryPeekBits(int count, out int readCount) { if (count < 0 || count > 32) { throw new ArgumentOutOfRangeException("count", "Must return between 0 and 32 bits!"); } if (_bitsLeft == 0 || count == 0) { readCount = 0; return 0; } int num = _buf[_start]; if (count < _bitsLeft) { num >>= _bitsLeft - count; num &= (1 << count) - 1; readCount = count; return num; } num &= (1 << _bitsLeft) - 1; count -= _bitsLeft; readCount = _bitsLeft; int num2 = _start; while (count > 0 && (num2 = (num2 + 1) % _buf.Length) != _end + 1) { int num3 = Math.Min(count, 8); num <<= num3; num |= _buf[num2] >> (8 - num3) % 8; count -= num3; readCount += num3; } return num; } public void SkipBits(int count) { if (count > 0) { if (count > BitsAvailable) { throw new ArgumentOutOfRangeException("count"); } int num = 8 - _bitsLeft + count; _start = (num / 8 + _start) % _buf.Length; _bitsLeft = 8 - num % 8; _bitsRead += count; } } public void RewindBits(int count) { _bitsLeft += count; _bitsRead -= count; while (_bitsLeft > 8) { _start--; _bitsLeft -= 8; } while (_start < 0) { _start += _buf.Length; } } public void FlushBits() { if (_bitsLeft < 8) { SkipBits(_bitsLeft); } } public void Reset() { _start = 0; _end = -1; _bitsLeft = 0; } } internal abstract class FrameBase { private static int _totalAllocation; private MpegStreamReader _reader; private byte[] _savedBuffer; internal static int TotalAllocation => Interlocked.CompareExchange(ref _totalAllocation, 0, 0); internal long Offset { get; private set; } internal int Length { get; set; } internal bool Validate(long offset, MpegStreamReader reader) { Offset = offset; _reader = reader; int num = Validate(); if (num > 0) { Length = num; return true; } return false; } protected int Read(int offset, byte[] buffer) { return Read(offset, buffer, 0, buffer.Length); } protected int Read(int offset, byte[] buffer, int index, int count) { if (_savedBuffer != null) { if (index < 0 || index + count > buffer.Length) { return 0; } if (offset < 0 || offset >= _savedBuffer.Length) { return 0; } if (offset + count > _savedBuffer.Length) { count = _savedBuffer.Length - index; } Array.Copy(_savedBuffer, offset, buffer, index, count); return count; } return _reader.Read(Offset + offset, buffer, index, count); } protected int ReadByte(int offset) { if (_savedBuffer != null) { if (offset < 0) { throw new ArgumentOutOfRangeException(); } if (offset >= _savedBuffer.Length) { return -1; } return _savedBuffer[offset]; } return _reader.ReadByte(Offset + offset); } protected abstract int Validate(); internal void SaveBuffer() { _savedBuffer = new byte[Length]; _reader.Read(Offset, _savedBuffer, 0, Length); Interlocked.Add(ref _totalAllocation, Length); } internal void ClearBuffer() { Interlocked.Add(ref _totalAllocation, -Length); _savedBuffer = null; } internal virtual void Parse() { } } internal class Huffman { private class HuffmanListNode { internal byte Value; internal int Length; internal int Bits; internal int Mask; internal HuffmanListNode Next; } private static readonly byte[][,] _codeTables; private static readonly float[] _floatLookup; private static HuffmanListNode[] _llCache; private static int[] _llCacheMaxBits; private static readonly int[] LIN_BITS; static Huffman() { _codeTables = new byte[17][,] { new byte[7, 2] { { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 } }, new byte[17, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 } }, new byte[17, 2] { { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 2, 1 }, { 0, 16 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 } }, new byte[31, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 19 }, { 2, 1 }, { 0, 49 }, { 2, 1 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 51 } }, new byte[31, 2] { { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 0, 17 }, { 6, 1 }, { 2, 1 }, { 0, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 6, 1 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 2, 1 }, { 0, 3 }, { 0, 51 } }, new byte[71, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 8, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 33 }, { 18, 1 }, { 6, 1 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 3 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 4 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 65 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 67 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 52 }, { 0, 5 }, { 0, 81 }, { 6, 1 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 4, 1 }, { 2, 1 }, { 0, 83 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 85 } }, new byte[71, 2] { { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 34 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 2, 1 }, { 0, 65 }, { 2, 1 }, { 0, 20 }, { 0, 66 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 36 }, { 2, 1 }, { 0, 51 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 6, 1 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 6, 1 }, { 2, 1 }, { 0, 37 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 2, 1 }, { 0, 83 }, { 2, 1 }, { 0, 69 }, { 2, 1 }, { 0, 84 }, { 0, 85 } }, new byte[71, 2] { { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 0, 49 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 80 }, { 0, 67 }, { 2, 1 }, { 0, 52 }, { 0, 81 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 21 }, { 0, 82 }, { 2, 1 }, { 0, 37 }, { 0, 68 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 84 }, { 0, 83 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 69 }, { 0, 85 } }, new byte[127, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 10, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 28, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 3 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 64 }, { 4, 1 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 28, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 0, 96 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 54 }, { 0, 113 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 23 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 0, 6 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 53 }, { 0, 69 }, { 0, 98 }, { 2, 1 }, { 0, 112 }, { 2, 1 }, { 0, 7 }, { 0, 100 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 6, 1 }, { 2, 1 }, { 0, 99 }, { 2, 1 }, { 0, 84 }, { 0, 85 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 55 }, { 0, 101 }, { 2, 1 }, { 0, 86 }, { 0, 116 }, { 6, 1 }, { 2, 1 }, { 0, 71 }, { 2, 1 }, { 0, 102 }, { 0, 117 }, { 4, 1 }, { 2, 1 }, { 0, 87 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[127, 2] { { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 8, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 18 }, { 24, 1 }, { 8, 1 }, { 2, 1 }, { 0, 33 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 30, 1 }, { 16, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 67 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 52 }, { 0, 81 }, { 0, 97 }, { 6, 1 }, { 2, 1 }, { 0, 22 }, { 2, 1 }, { 0, 6 }, { 0, 38 }, { 2, 1 }, { 0, 98 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 16, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 37 }, { 0, 68 }, { 0, 96 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 23 }, { 0, 113 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 7 }, { 0, 100 }, { 0, 114 }, { 2, 1 }, { 0, 39 }, { 4, 1 }, { 2, 1 }, { 0, 83 }, { 0, 53 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 2, 1 }, { 0, 101 }, { 0, 86 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 85 }, { 0, 87 }, { 0, 116 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[127, 2] { { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 16, 1 }, { 4, 1 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 49 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 64 }, { 26, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 2, 1 }, { 0, 65 }, { 0, 51 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 20 }, { 0, 66 }, { 2, 1 }, { 0, 36 }, { 2, 1 }, { 0, 4 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 28, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 2, 1 }, { 0, 83 }, { 0, 53 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 22 }, { 0, 97 }, { 4, 1 }, { 2, 1 }, { 0, 98 }, { 0, 38 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 6 }, { 0, 68 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 0, 113 }, { 4, 1 }, { 2, 1 }, { 0, 23 }, { 0, 100 }, { 2, 1 }, { 0, 70 }, { 0, 114 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 39 }, { 2, 1 }, { 0, 85 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 0, 86 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 101 }, { 0, 116 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[511, 2] { { 2, 1 }, { 0, 0 }, { 6, 1 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 28, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 49 }, { 6, 1 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 70, 1 }, { 28, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 4, 1 }, { 2, 1 }, { 0, 36 }, { 0, 80 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 4, 1 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 2, 1 }, { 0, 37 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 4, 1 }, { 2, 1 }, { 0, 128 }, { 0, 8 }, { 0, 129 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 53 }, { 0, 98 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 4, 1 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 2, 1 }, { 0, 54 }, { 0, 112 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 7 }, { 0, 85 }, { 0, 113 }, { 2, 1 }, { 0, 23 }, { 2, 1 }, { 0, 39 }, { 0, 55 }, { 72, 1 }, { 24, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 24 }, { 0, 130 }, { 2, 1 }, { 0, 40 }, { 4, 1 }, { 2, 1 }, { 0, 100 }, { 0, 70 }, { 0, 114 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 2, 1 }, { 0, 144 }, { 0, 9 }, { 2, 1 }, { 0, 145 }, { 0, 25 }, { 24, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 115 }, { 0, 101 }, { 2, 1 }, { 0, 86 }, { 0, 116 }, { 4, 1 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 0, 131 }, { 6, 1 }, { 2, 1 }, { 0, 56 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 146 }, { 0, 41 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 103 }, { 0, 133 }, { 2, 1 }, { 0, 88 }, { 0, 57 }, { 2, 1 }, { 0, 147 }, { 2, 1 }, { 0, 73 }, { 0, 134 }, { 6, 1 }, { 2, 1 }, { 0, 160 }, { 2, 1 }, { 0, 104 }, { 0, 10 }, { 2, 1 }, { 0, 161 }, { 0, 26 }, { 68, 1 }, { 24, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 4, 1 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 2, 1 }, { 0, 163 }, { 0, 58 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 74 }, { 0, 150 }, { 2, 1 }, { 0, 176 }, { 0, 11 }, { 2, 1 }, { 0, 177 }, { 0, 27 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 178 }, { 4, 1 }, { 2, 1 }, { 0, 118 }, { 0, 119 }, { 0, 148 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 135 }, { 0, 120 }, { 0, 164 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 165 }, { 0, 43 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 90 }, { 0, 136 }, { 0, 179 }, { 2, 1 }, { 0, 59 }, { 2, 1 }, { 0, 121 }, { 0, 166 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 106 }, { 0, 180 }, { 0, 192 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 152 }, { 0, 193 }, { 60, 1 }, { 22, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 28 }, { 2, 1 }, { 0, 137 }, { 0, 181 }, { 2, 1 }, { 0, 91 }, { 0, 194 }, { 4, 1 }, { 2, 1 }, { 0, 44 }, { 0, 60 }, { 4, 1 }, { 2, 1 }, { 0, 182 }, { 0, 107 }, { 2, 1 }, { 0, 196 }, { 0, 76 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 168 }, { 0, 138 }, { 2, 1 }, { 0, 208 }, { 0, 13 }, { 2, 1 }, { 0, 209 }, { 2, 1 }, { 0, 75 }, { 2, 1 }, { 0, 151 }, { 0, 167 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 195 }, { 2, 1 }, { 0, 122 }, { 0, 153 }, { 4, 1 }, { 2, 1 }, { 0, 197 }, { 0, 92 }, { 0, 183 }, { 4, 1 }, { 2, 1 }, { 0, 29 }, { 0, 210 }, { 2, 1 }, { 0, 45 }, { 2, 1 }, { 0, 123 }, { 0, 211 }, { 52, 1 }, { 28, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 4, 1 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 2, 1 }, { 0, 154 }, { 0, 212 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 184 }, { 0, 139 }, { 2, 1 }, { 0, 77 }, { 0, 199 }, { 4, 1 }, { 2, 1 }, { 0, 124 }, { 0, 213 }, { 2, 1 }, { 0, 93 }, { 0, 224 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 225 }, { 0, 30 }, { 4, 1 }, { 2, 1 }, { 0, 14 }, { 0, 46 }, { 0, 226 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 227 }, { 0, 109 }, { 2, 1 }, { 0, 140 }, { 0, 228 }, { 4, 1 }, { 2, 1 }, { 0, 229 }, { 0, 186 }, { 0, 240 }, { 38, 1 }, { 16, 1 }, { 4, 1 }, { 2, 1 }, { 0, 241 }, { 0, 31 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 170 }, { 0, 155 }, { 0, 185 }, { 2, 1 }, { 0, 62 }, { 2, 1 }, { 0, 214 }, { 0, 200 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 78 }, { 2, 1 }, { 0, 215 }, { 0, 125 }, { 2, 1 }, { 0, 171 }, { 2, 1 }, { 0, 94 }, { 0, 201 }, { 6, 1 }, { 2, 1 }, { 0, 15 }, { 2, 1 }, { 0, 156 }, { 0, 110 }, { 2, 1 }, { 0, 242 }, { 0, 47 }, { 32, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 141 }, { 0, 63 }, { 6, 1 }, { 2, 1 }, { 0, 243 }, { 2, 1 }, { 0, 230 }, { 0, 202 }, { 2, 1 }, { 0, 244 }, { 0, 79 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 187 }, { 0, 172 }, { 2, 1 }, { 0, 231 }, { 0, 245 }, { 4, 1 }, { 2, 1 }, { 0, 217 }, { 0, 157 }, { 2, 1 }, { 0, 95 }, { 0, 232 }, { 30, 1 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 111 }, { 2, 1 }, { 0, 246 }, { 0, 203 }, { 4, 1 }, { 2, 1 }, { 0, 188 }, { 0, 173 }, { 0, 218 }, { 8, 1 }, { 2, 1 }, { 0, 247 }, { 4, 1 }, { 2, 1 }, { 0, 126 }, { 0, 127 }, { 0, 142 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 174 }, { 0, 204 }, { 2, 1 }, { 0, 248 }, { 0, 143 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 2, 1 }, { 0, 234 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 235 }, { 2, 1 }, { 0, 190 }, { 2, 1 }, { 0, 205 }, { 0, 250 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 233 }, { 0, 175 }, { 0, 220 }, { 2, 1 }, { 0, 206 }, { 0, 251 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 191 }, { 0, 222 }, { 2, 1 }, { 0, 207 }, { 0, 238 }, { 4, 1 }, { 2, 1 }, { 0, 223 }, { 0, 239 }, { 2, 1 }, { 0, 255 }, { 2, 1 }, { 0, 237 }, { 2, 1 }, { 0, 253 }, { 2, 1 }, { 0, 252 }, { 0, 254 } }, new byte[511, 2] { { 16, 1 }, { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 50, 1 }, { 16, 1 }, { 6, 1 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 49 }, { 6, 1 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 3 }, { 0, 64 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 20 }, { 0, 65 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 2, 1 }, { 0, 36 }, { 0, 67 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 52 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 0, 97 }, { 90, 1 }, { 36, 1 }, { 18, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 2, 1 }, { 0, 22 }, { 0, 98 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 54 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 2, 1 }, { 0, 113 }, { 0, 85 }, { 4, 1 }, { 2, 1 }, { 0, 23 }, { 0, 100 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 24, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 0, 101 }, { 4, 1 }, { 2, 1 }, { 0, 86 }, { 0, 128 }, { 2, 1 }, { 0, 8 }, { 0, 116 }, { 4, 1 }, { 2, 1 }, { 0, 129 }, { 0, 24 }, { 2, 1 }, { 0, 130 }, { 0, 40 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 144 }, { 0, 25 }, { 0, 145 }, { 4, 1 }, { 2, 1 }, { 0, 146 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 41 }, { 92, 1 }, { 36, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 4, 1 }, { 2, 1 }, { 0, 9 }, { 0, 119 }, { 0, 147 }, { 4, 1 }, { 2, 1 }, { 0, 57 }, { 0, 148 }, { 2, 1 }, { 0, 73 }, { 0, 134 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 104 }, { 2, 1 }, { 0, 160 }, { 0, 10 }, { 2, 1 }, { 0, 161 }, { 0, 26 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 26, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 163 }, { 2, 1 }, { 0, 58 }, { 0, 135 }, { 4, 1 }, { 2, 1 }, { 0, 120 }, { 0, 164 }, { 2, 1 }, { 0, 74 }, { 0, 150 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 176 }, { 0, 177 }, { 4, 1 }, { 2, 1 }, { 0, 27 }, { 0, 165 }, { 0, 178 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 90 }, { 0, 43 }, { 2, 1 }, { 0, 136 }, { 0, 151 }, { 2, 1 }, { 0, 179 }, { 2, 1 }, { 0, 121 }, { 0, 59 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 106 }, { 0, 180 }, { 2, 1 }, { 0, 75 }, { 0, 193 }, { 4, 1 }, { 2, 1 }, { 0, 152 }, { 0, 137 }, { 2, 1 }, { 0, 28 }, { 0, 181 }, { 80, 1 }, { 34, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 91 }, { 0, 44 }, { 0, 194 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 11 }, { 0, 192 }, { 0, 166 }, { 2, 1 }, { 0, 167 }, { 0, 122 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 195 }, { 0, 60 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 153 }, { 0, 182 }, { 4, 1 }, { 2, 1 }, { 0, 107 }, { 0, 196 }, { 2, 1 }, { 0, 76 }, { 0, 168 }, { 20, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 138 }, { 0, 197 }, { 4, 1 }, { 2, 1 }, { 0, 208 }, { 0, 92 }, { 0, 209 }, { 4, 1 }, { 2, 1 }, { 0, 183 }, { 0, 123 }, { 2, 1 }, { 0, 29 }, { 2, 1 }, { 0, 13 }, { 0, 45 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 210 }, { 0, 211 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 154 }, { 0, 184 }, { 0, 212 }, { 4, 1 }, { 2, 1 }, { 0, 139 }, { 0, 77 }, { 2, 1 }, { 0, 199 }, { 0, 124 }, { 68, 1 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 213 }, { 0, 93 }, { 4, 1 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 0, 225 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 226 }, { 2, 1 }, { 0, 170 }, { 0, 46 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 185 }, { 0, 155 }, { 2, 1 }, { 0, 227 }, { 0, 214 }, { 4, 1 }, { 2, 1 }, { 0, 109 }, { 0, 62 }, { 2, 1 }, { 0, 200 }, { 0, 140 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 228 }, { 0, 78 }, { 2, 1 }, { 0, 215 }, { 0, 125 }, { 4, 1 }, { 2, 1 }, { 0, 229 }, { 0, 186 }, { 2, 1 }, { 0, 171 }, { 0, 94 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 201 }, { 0, 156 }, { 2, 1 }, { 0, 241 }, { 0, 31 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 240 }, { 0, 110 }, { 0, 242 }, { 2, 1 }, { 0, 47 }, { 0, 230 }, { 38, 1 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 243 }, { 2, 1 }, { 0, 63 }, { 0, 244 }, { 6, 1 }, { 2, 1 }, { 0, 79 }, { 2, 1 }, { 0, 141 }, { 0, 217 }, { 2, 1 }, { 0, 187 }, { 0, 202 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 172 }, { 0, 231 }, { 2, 1 }, { 0, 126 }, { 0, 245 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 157 }, { 0, 95 }, { 2, 1 }, { 0, 232 }, { 0, 142 }, { 2, 1 }, { 0, 246 }, { 0, 203 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 15 }, { 0, 174 }, { 0, 111 }, { 2, 1 }, { 0, 188 }, { 0, 218 }, { 4, 1 }, { 2, 1 }, { 0, 173 }, { 0, 247 }, { 2, 1 }, { 0, 127 }, { 0, 233 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 204 }, { 2, 1 }, { 0, 248 }, { 0, 143 }, { 4, 1 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 2, 1 }, { 0, 234 }, { 0, 249 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 220 }, { 2, 1 }, { 0, 205 }, { 0, 235 }, { 4, 1 }, { 2, 1 }, { 0, 190 }, { 0, 250 }, { 2, 1 }, { 0, 175 }, { 0, 221 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 236 }, { 0, 206 }, { 0, 251 }, { 4, 1 }, { 2, 1 }, { 0, 191 }, { 0, 237 }, { 2, 1 }, { 0, 222 }, { 0, 252 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 207 }, { 0, 253 }, { 0, 238 }, { 4, 1 }, { 2, 1 }, { 0, 223 }, { 0, 254 }, { 2, 1 }, { 0, 239 }, { 0, 255 } }, new byte[511, 2] { { 2, 1 }, { 0, 0 }, { 6, 1 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 42, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 6, 1 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 4, 1 }, { 2, 1 }, { 0, 36 }, { 0, 80 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 138, 1 }, { 40, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 21 }, { 0, 81 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 0, 83 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 0, 97 }, { 2, 1 }, { 0, 22 }, { 0, 98 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 4, 1 }, { 2, 1 }, { 0, 54 }, { 0, 112 }, { 0, 113 }, { 40, 1 }, { 18, 1 }, { 8, 1 }, { 2, 1 }, { 0, 23 }, { 2, 1 }, { 0, 7 }, { 2, 1 }, { 0, 85 }, { 0, 100 }, { 4, 1 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 101 }, { 0, 115 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 55 }, { 2, 1 }, { 0, 86 }, { 0, 8 }, { 2, 1 }, { 0, 128 }, { 0, 129 }, { 6, 1 }, { 2, 1 }, { 0, 24 }, { 2, 1 }, { 0, 116 }, { 0, 71 }, { 2, 1 }, { 0, 130 }, { 2, 1 }, { 0, 40 }, { 0, 102 }, { 24, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 2, 1 }, { 0, 117 }, { 0, 132 }, { 4, 1 }, { 2, 1 }, { 0, 72 }, { 0, 144 }, { 0, 145 }, { 6, 1 }, { 2, 1 }, { 0, 25 }, { 2, 1 }, { 0, 9 }, { 0, 118 }, { 2, 1 }, { 0, 146 }, { 0, 41 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 2, 1 }, { 0, 147 }, { 0, 57 }, { 4, 1 }, { 2, 1 }, { 0, 160 }, { 0, 10 }, { 0, 26 }, { 8, 1 }, { 2, 1 }, { 0, 162 }, { 2, 1 }, { 0, 103 }, { 2, 1 }, { 0, 87 }, { 0, 73 }, { 6, 1 }, { 2, 1 }, { 0, 148 }, { 2, 1 }, { 0, 119 }, { 0, 134 }, { 2, 1 }, { 0, 161 }, { 2, 1 }, { 0, 104 }, { 0, 149 }, { 220, 1 }, { 126, 1 }, { 50, 1 }, { 26, 1 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 42 }, { 2, 1 }, { 0, 89 }, { 0, 58 }, { 2, 1 }, { 0, 163 }, { 2, 1 }, { 0, 135 }, { 0, 120 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 164 }, { 0, 74 }, { 2, 1 }, { 0, 150 }, { 0, 105 }, { 4, 1 }, { 2, 1 }, { 0, 176 }, { 0, 11 }, { 0, 177 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 27 }, { 0, 178 }, { 2, 1 }, { 0, 43 }, { 2, 1 }, { 0, 165 }, { 0, 90 }, { 6, 1 }, { 2, 1 }, { 0, 179 }, { 2, 1 }, { 0, 166 }, { 0, 106 }, { 4, 1 }, { 2, 1 }, { 0, 180 }, { 0, 75 }, { 2, 1 }, { 0, 12 }, { 0, 193 }, { 30, 1 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 181 }, { 0, 194 }, { 0, 44 }, { 4, 1 }, { 2, 1 }, { 0, 167 }, { 0, 195 }, { 2, 1 }, { 0, 107 }, { 0, 196 }, { 8, 1 }, { 2, 1 }, { 0, 29 }, { 4, 1 }, { 2, 1 }, { 0, 136 }, { 0, 151 }, { 0, 59 }, { 4, 1 }, { 2, 1 }, { 0, 209 }, { 0, 210 }, { 2, 1 }, { 0, 45 }, { 0, 211 }, { 18, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 46 }, { 0, 226 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 121 }, { 0, 152 }, { 0, 192 }, { 2, 1 }, { 0, 28 }, { 2, 1 }, { 0, 137 }, { 0, 91 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 60 }, { 2, 1 }, { 0, 122 }, { 0, 182 }, { 4, 1 }, { 2, 1 }, { 0, 76 }, { 0, 153 }, { 2, 1 }, { 0, 168 }, { 0, 138 }, { 6, 1 }, { 2, 1 }, { 0, 13 }, { 2, 1 }, { 0, 197 }, { 0, 92 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 2, 1 }, { 0, 108 }, { 0, 154 }, { 88, 1 }, { 86, 1 }, { 36, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 139 }, { 0, 77 }, { 2, 1 }, { 0, 199 }, { 0, 124 }, { 4, 1 }, { 2, 1 }, { 0, 213 }, { 0, 93 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 8, 1 }, { 2, 1 }, { 0, 227 }, { 4, 1 }, { 2, 1 }, { 0, 208 }, { 0, 183 }, { 0, 123 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 169 }, { 0, 184 }, { 0, 212 }, { 2, 1 }, { 0, 225 }, { 2, 1 }, { 0, 170 }, { 0, 185 }, { 24, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 155 }, { 0, 214 }, { 0, 109 }, { 2, 1 }, { 0, 62 }, { 0, 200 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 140 }, { 0, 228 }, { 0, 78 }, { 4, 1 }, { 2, 1 }, { 0, 215 }, { 0, 229 }, { 2, 1 }, { 0, 186 }, { 0, 171 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 156 }, { 0, 230 }, { 4, 1 }, { 2, 1 }, { 0, 110 }, { 0, 216 }, { 2, 1 }, { 0, 141 }, { 0, 187 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 231 }, { 0, 157 }, { 2, 1 }, { 0, 232 }, { 0, 142 }, { 4, 1 }, { 2, 1 }, { 0, 203 }, { 0, 188 }, { 0, 158 }, { 0, 241 }, { 2, 1 }, { 0, 31 }, { 2, 1 }, { 0, 15 }, { 0, 47 }, { 66, 1 }, { 56, 1 }, { 2, 1 }, { 0, 242 }, { 52, 1 }, { 50, 1 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 189 }, { 2, 1 }, { 0, 94 }, { 2, 1 }, { 0, 125 }, { 0, 201 }, { 6, 1 }, { 2, 1 }, { 0, 202 }, { 2, 1 }, { 0, 172 }, { 0, 126 }, { 4, 1 }, { 2, 1 }, { 0, 218 }, { 0, 173 }, { 0, 204 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 174 }, { 2, 1 }, { 0, 219 }, { 0, 220 }, { 2, 1 }, { 0, 205 }, { 0, 190 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 235 }, { 0, 237 }, { 0, 238 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 217 }, { 0, 234 }, { 0, 233 }, { 2, 1 }, { 0, 222 }, { 4, 1 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 0, 206 }, { 0, 63 }, { 0, 240 }, { 4, 1 }, { 2, 1 }, { 0, 243 }, { 0, 244 }, { 2, 1 }, { 0, 79 }, { 2, 1 }, { 0, 245 }, { 0, 95 }, { 10, 1 }, { 2, 1 }, { 0, 255 }, { 4, 1 }, { 2, 1 }, { 0, 246 }, { 0, 111 }, { 2, 1 }, { 0, 247 }, { 0, 127 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 143 }, { 2, 1 }, { 0, 248 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 250 }, { 0, 175 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 251 }, { 0, 191 }, { 2, 1 }, { 0, 252 }, { 0, 207 }, { 4, 1 }, { 2, 1 }, { 0, 253 }, { 0, 223 }, { 2, 1 }, { 0, 254 }, { 0, 239 } }, new byte[512, 2] { { 60, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 20 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 250, 1 }, { 98, 1 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 4, 1 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 2, 1 }, { 0, 98 }, { 0, 38 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 113 }, { 0, 85 }, { 2, 1 }, { 0, 100 }, { 0, 70 }, { 32, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 114 }, { 2, 1 }, { 0, 39 }, { 0, 55 }, { 2, 1 }, { 0, 115 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 0, 23 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 101 }, { 0, 86 }, { 4, 1 }, { 2, 1 }, { 0, 128 }, { 0, 8 }, { 0, 129 }, { 4, 1 }, { 2, 1 }, { 0, 116 }, { 0, 71 }, { 2, 1 }, { 0, 24 }, { 0, 130 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 40 }, { 0, 102 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 145 }, { 0, 25 }, { 2, 1 }, { 0, 146 }, { 0, 118 }, { 4, 1 }, { 2, 1 }, { 0, 103 }, { 0, 41 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 92, 1 }, { 34, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 147 }, { 0, 57 }, { 2, 1 }, { 0, 148 }, { 0, 73 }, { 4, 1 }, { 2, 1 }, { 0, 119 }, { 0, 134 }, { 2, 1 }, { 0, 104 }, { 0, 161 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 4, 1 }, { 2, 1 }, { 0, 163 }, { 0, 58 }, { 2, 1 }, { 0, 135 }, { 2, 1 }, { 0, 120 }, { 0, 74 }, { 22, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 164 }, { 0, 150 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 177 }, { 2, 1 }, { 0, 27 }, { 0, 165 }, { 6, 1 }, { 2, 1 }, { 0, 178 }, { 2, 1 }, { 0, 90 }, { 0, 43 }, { 2, 1 }, { 0, 136 }, { 0, 179 }, { 16, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 144 }, { 2, 1 }, { 0, 9 }, { 0, 160 }, { 2, 1 }, { 0, 151 }, { 0, 121 }, { 4, 1 }, { 2, 1 }, { 0, 166 }, { 0, 106 }, { 0, 180 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 26 }, { 2, 1 }, { 0, 10 }, { 0, 176 }, { 2, 1 }, { 0, 59 }, { 2, 1 }, { 0, 11 }, { 0, 192 }, { 4, 1 }, { 2, 1 }, { 0, 75 }, { 0, 193 }, { 2, 1 }, { 0, 152 }, { 0, 137 }, { 67, 1 }, { 34, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 28 }, { 0, 181 }, { 2, 1 }, { 0, 91 }, { 0, 194 }, { 4, 1 }, { 2, 1 }, { 0, 44 }, { 0, 167 }, { 2, 1 }, { 0, 122 }, { 0, 195 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 60 }, { 2, 1 }, { 0, 12 }, { 0, 208 }, { 2, 1 }, { 0, 182 }, { 0, 107 }, { 4, 1 }, { 2, 1 }, { 0, 196 }, { 0, 76 }, { 2, 1 }, { 0, 153 }, { 0, 168 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 138 }, { 0, 197 }, { 2, 1 }, { 0, 92 }, { 0, 209 }, { 4, 1 }, { 2, 1 }, { 0, 183 }, { 0, 123 }, { 2, 1 }, { 0, 29 }, { 0, 210 }, { 9, 1 }, { 4, 1 }, { 2, 1 }, { 0, 45 }, { 0, 211 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 85, 250 }, { 4, 1 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 2, 1 }, { 0, 154 }, { 0, 212 }, { 32, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 184 }, { 0, 139 }, { 2, 1 }, { 0, 77 }, { 0, 199 }, { 4, 1 }, { 2, 1 }, { 0, 124 }, { 0, 213 }, { 2, 1 }, { 0, 93 }, { 0, 225 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 226 }, { 2, 1 }, { 0, 170 }, { 0, 185 }, { 4, 1 }, { 2, 1 }, { 0, 155 }, { 0, 227 }, { 2, 1 }, { 0, 214 }, { 0, 109 }, { 20, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 62 }, { 2, 1 }, { 0, 46 }, { 0, 78 }, { 2, 1 }, { 0, 200 }, { 0, 140 }, { 4, 1 }, { 2, 1 }, { 0, 228 }, { 0, 215 }, { 4, 1 }, { 2, 1 }, { 0, 125 }, { 0, 171 }, { 0, 229 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 186 }, { 0, 94 }, { 2, 1 }, { 0, 201 }, { 2, 1 }, { 0, 156 }, { 0, 110 }, { 8, 1 }, { 2, 1 }, { 0, 230 }, { 2, 1 }, { 0, 13 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 141 }, { 2, 1 }, { 0, 187 }, { 0, 202 }, { 74, 1 }, { 2, 1 }, { 0, 255 }, { 64, 1 }, { 58, 1 }, { 32, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 172 }, { 0, 231 }, { 2, 1 }, { 0, 126 }, { 0, 217 }, { 4, 1 }, { 2, 1 }, { 0, 157 }, { 0, 232 }, { 2, 1 }, { 0, 142 }, { 0, 203 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 188 }, { 0, 218 }, { 2, 1 }, { 0, 173 }, { 0, 233 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 204 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 234 }, { 0, 174 }, { 2, 1 }, { 0, 220 }, { 0, 205 }, { 4, 1 }, { 2, 1 }, { 0, 235 }, { 0, 190 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 206 }, { 0, 237 }, { 2, 1 }, { 0, 222 }, { 0, 238 }, { 0, 15 }, { 4, 1 }, { 2, 1 }, { 0, 240 }, { 0, 31 }, { 0, 241 }, { 4, 1 }, { 2, 1 }, { 0, 242 }, { 0, 47 }, { 2, 1 }, { 0, 243 }, { 0, 63 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 244 }, { 0, 79 }, { 2, 1 }, { 0, 245 }, { 0, 95 }, { 4, 1 }, { 2, 1 }, { 0, 246 }, { 0, 111 }, { 2, 1 }, { 0, 247 }, { 2, 1 }, { 0, 127 }, { 0, 143 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 248 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 175 }, { 0, 250 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 251 }, { 0, 191 }, { 2, 1 }, { 0, 252 }, { 0, 207 }, { 4, 1 }, { 2, 1 }, { 0, 253 }, { 0, 223 }, { 2, 1 }, { 0, 254 }, { 0, 239 } }, new byte[31, 2] { { 2, 1 }, { 0, 0 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 8 }, { 0, 4 }, { 2, 1 }, { 0, 1 }, { 0, 2 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 10 }, { 2, 1 }, { 0, 3 }, { 0, 6 }, { 6, 1 }, { 2, 1 }, { 0, 9 }, { 2, 1 }, { 0, 5 }, { 0, 7 }, { 4, 1 }, { 2, 1 }, { 0, 14 }, { 0, 13 }, { 2, 1 }, { 0, 15 }, { 0, 11 } }, new byte[31, 2] { { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 1 }, { 2, 1 }, { 0, 2 }, { 0, 3 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 5 }, { 2, 1 }, { 0, 6 }, { 0, 7 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 8 }, { 0, 9 }, { 2, 1 }, { 0, 10 }, { 0, 11 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 13 }, { 2, 1 }, { 0, 14 }, { 0, 15 } } }; _llCache = new HuffmanListNode[_codeTables.Length]; _llCacheMaxBits = new int[_codeTables.Length]; LIN_BITS = new int[32] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13 }; _floatLookup = new float[8207]; for (int i = 0; i < 8207; i++) { _floatLookup[i] = (float)Math.Pow(i, 1.3333333333333333); } } internal static void Decode(BitReservoir br, int table, out float x, out float y) { if (table == 0 || table == 4 || table == 14) { x = (y = 0f); return; } byte num = DecodeSymbol(br, table); int num2 = num >> 4; int num3 = num & 0xF; int num4 = LIN_BITS[table]; if (num4 > 0 && num2 == 15) { num2 += br.GetBits(num4); } if (num2 != 0 && br.Get1Bit() != 0) { x = 0f - _floatLookup[num2]; } else { x = _floatLookup[num2]; } if (num4 > 0 && num3 == 15) { num3 += br.GetBits(num4); } if (num3 != 0 && br.Get1Bit() != 0) { y = 0f - _floatLookup[num3]; } else { y = _floatLookup[num3]; } } internal static void Decode(BitReservoir br, int table, out float x, out float y, out float v, out float w) { byte num = DecodeSymbol(br, table); v = (w = (x = (y = 0f))); if ((num & 8u) != 0) { if (br.Get1Bit() == 1) { v = 0f - _floatLookup[1]; } else { v = _floatLookup[1]; } } if ((num & 4u) != 0) { if (br.Get1Bit() == 1) { w = 0f - _floatLookup[1]; } else { w = _floatLookup[1]; } } if ((num & 2u) != 0) { if (br.Get1Bit() == 1) { x = 0f - _floatLookup[1]; } else { x = _floatLookup[1]; } } if (((uint)num & (true ? 1u : 0u)) != 0) { if (br.Get1Bit() == 1) { y = 0f - _floatLookup[1]; } else { y = _floatLookup[1]; } } } private static byte DecodeSymbol(BitReservoir br, int table) { int maxBits; HuffmanListNode huffmanListNode = GetNode(table, out maxBits); int readCount; int num = br.TryPeekBits(maxBits, out readCount); if (readCount < maxBits) { num <<= maxBits - readCount; } while (huffmanListNode != null && huffmanListNode.Length <= readCount) { if ((num & huffmanListNode.Mask) == huffmanListNode.Bits) { br.SkipBits(huffmanListNode.Length); break; } huffmanListNode = huffmanListNode.Next; } if (huffmanListNode != null && huffmanListNode.Length <= readCount) { return huffmanListNode.Value; } return 0; } private static HuffmanListNode GetNode(int table, out int maxBits) { int num = table; if (num > 16) { num = ((num > 31) ? (num - 17) : ((num < 24) ? 13 : 14)); } else { if (num > 13) { num--; } if (num > 3) { num--; } num--; } if (_llCache[num] == null) { _llCache[num] = InitTable(_codeTables[num], out maxBits); _llCacheMaxBits[num] = maxBits; } else { maxBits = _llCacheMaxBits[num]; } return _llCache[num]; } private static HuffmanListNode InitTable(byte[,] tree, out int maxBits) { List<byte> list = new List<byte>(); List<int> list2 = new List<int>(); List<int> list3 = new List<int>(); int length = tree.GetLength(0); for (int i = 0; i < length; i++) { if (tree[i, 0] == 0) { int num = 0; int item = 0; int num2 = i; do { num2 = FindPreviousNode(tree, num2, out var bit); num |= bit << item++; } while (num2 > 0); list.Add(tree[i, 1]); list2.Add(item); list3.Add(num); } } return BuildLinkedList(list, list2, list3, out maxBits); } private static int FindPreviousNode(byte[,] tree, int idx, out int bit) { for (int num = idx - 1; num >= 0; num--) { if (tree[num, 0] != 0) { for (int i = 0; i < 2; i++) { if (num + tree[num, i] != idx) { continue; } if (tree[num, i] >= 250) { int result = FindPreviousNode(tree, num, out bit); if (bit != i) { throw new InvalidOperationException(); } return result; } bit = i; return num; } } } throw new InvalidOperationException(); } private static HuffmanListNode BuildLinkedList(List<byte> values, List<int> lengthList, List<int> codeList, out int maxBits) { HuffmanListNode[] array = new HuffmanListNode[lengthList.Count]; maxBits = lengthList.Max(); for (int j = 0; j < array.Length; j++) { int num = maxBits - lengthList[j]; array[j] = new HuffmanListNode { Value = values[j], Length = lengthList[j], Bits = codeList[j] << num, Mask = (1 << lengthList[j]) - 1 << num }; } Array.Sort(array, (HuffmanListNode i1, HuffmanListNode i2) => i1.Length - i2.Length); for (int k = 1; k < array.Length && array[k].Length < 99999; k++) { array[k - 1].Next = array[k]; } return array[0]; } } internal class ID3Frame : FrameBase { private int _version; internal int Version { get { if (_version == 0) { return 1; } return _version; } } internal static ID3Frame TrySync(uint syncMark) { if ((syncMark & 0xFFFFFF00u) == 1229206272) { return new ID3Frame { _version = 2 }; } if ((syncMark & 0xFFFFFF00u) == 1413564160) { if ((syncMark & 0xFF) == 43) { return new ID3Frame { _version = 1 }; } return new ID3Frame { _version = 0 }; } return null; } private ID3Frame() { } protected override int Validate() { switch (_version) { case 2: { byte[] array = new byte[7]; if (Read(3, array) == 7) { byte b; switch (array[0]) { case 2: b = 63; break; case 3: b = 31; break; case 4: b = 15; break; default: return -1; } int num = (array[3] << 21) | (array[4] << 14) | (array[5] << 7) | array[6]; if (((array[2] & b) | (array[3] & 0x80) | (array[4] & 0x80) | (array[5] & 0x80) | (array[6] & 0x80)) == 0 && array[1] != byte.MaxValue) { return num + 10; } } break; } case 1: return 355; case 0: return 128; } return -1; } internal override void Parse() { switch (_version) { case 2: ParseV2(); break; case 1: ParseV1Enh(); break; case 0: ParseV1(3); break; } } private void ParseV1(int offset) { } private void ParseV1Enh() { ParseV1(230); } private void ParseV2() { } internal void Merge(ID3Frame newFrame) { } } internal abstract class LayerDecoderBase { protected const int SBLIMIT = 32; private const float INV_SQRT_2 = 0.70710677f; private static float[] DEWINDOW_TABLE = new float[512] { 0f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -3.0518E-05f, -3.0518E-05f, -3.0518E-05f, -3.0518E-05f, -4.5776E-05f, -4.5776E-05f, -6.1035E-05f, -6.1035E-05f, -7.6294E-05f, -7.6294E-05f, -9.1553E-05f, -0.000106812f, -0.000106812f, -0.00012207f, -0.000137329f, -0.000152588f, -0.000167847f, -0.000198364f, -0.000213623f, -0.000244141f, -0.000259399f, -0.000289917f, -0.000320435f, -0.000366211f, -0.000396729f, -0.000442505f, -0.000473022f, -0.000534058f, -0.000579834f, -0.00062561f, -0.000686646f, -0.000747681f, -0.000808716f, -0.00088501f, -0.000961304f, -0.001037598f, -0.001113892f, -0.001205444f, -0.001296997f, -0.00138855f, -0.001480103f, -0.001586914f, -0.001693726f, -0.001785278f, -0.001907349f, -0.00201416f, -0.002120972f, -0.002243042f, -0.002349854f, -0.002456665f, -0.002578735f, -0.002685547f, -0.002792358f, -0.00289917f, -0.002990723f, -0.003082275f, -0.003173828f, 0.003250122f, 0.003326416f, 0.003387451f, 0.003433228f, 0.003463745f, 0.003479004f, 0.003479004f, 0.003463745f, 0.003417969f, 0.003372192f, 0.00328064f, 0.003173828f, 0.003051758f, 0.002883911f, 0.002700806f, 0.002487183f, 0.002227783f, 0.001937866f, 0.001617432f, 0.001266479f, 0.000869751f, 0.000442505f, -3.0518E-05f, -0.000549316f, -0.001098633f, -0.001693726f, -0.002334595f, -0.003005981f, -0.003723145f, -0.004486084f, -0.0052948f, -0.006118774f, -0.007003784f, -0.007919312f, -0.008865356f, -0.009841919f, -0.010848999f, -0.011886597f, -0.012939453f, -0.014022827f, -0.01512146f, -0.016235352f, -0.017349243f, -0.018463135f, -0.019577026f, -0.020690918f, -0.02178955f, -0.022857666f, -0.023910522f, -0.024932861f, -0.025909424f, -0.02684021f, -0.02772522f, -0.028533936f, -0.029281616f, -0.029937744f, -0.030532837f, -0.03100586f, -0.03138733f, -0.031661987f, -0.031814575f, -0.031845093f, -0.03173828f, -0.03147888f, 0.031082153f, 0.030517578f, 0.029785156f, 0.028884888f, 0.027801514f, 0.026535034f, 0.02508545f, 0.023422241f, 0.021575928f, 0.01953125f, 0.01725769f, 0.014801025f, 0.012115479f, 0.009231567f, 0.006134033f, 0.002822876f, -0.000686646f, -0.004394531f, -0.00831604f, -0.012420654f, -0.016708374f, -0.0211792f, -0.025817871f, -0.03060913f, -0.03555298f, -0.040634155f, -0.045837402f, -0.051132202f, -0.056533813f, -0.06199646f, -0.06752014f, -0.07305908f, -0.07862854f, -0.08418274f, -0.08970642f, -0.09516907f, -0.10054016f, -0.1058197f, -0.110946655f, -0.11592102f, -0.12069702f, -0.1252594f, -0.12956238f, -0.1335907f, -0.13729858f, -0.14067078f, -0.14367676f, -0.1462555f, -0.14842224f, -0.15011597f, -0.15130615f, -0.15196228f, -0.15206909f, -0.15159607f, -0.15049744f, -0.1487732f, -0.1463623f, -0.14326477f, -0.13945007f, -0.1348877f, -0.12957764f, -0.12347412f, -0.11657715f, -0.1088562f, 0.10031128f, 0.090927124f, 0.08068848f, 0.06959534f, 0.057617188f, 0.044784546f, 0.031082153f, 0.01651001f, 0.001068115f, -0.015228271f, -0.03237915f, -0.050354004f, -0.06916809f, -0.088775635f, -0.10916138f, -0.13031006f, -0.15220642f, -0.17478943f, -0.19805908f, -0.22198486f, -0.24650574f, -0.2715912f, -0.2972107f, -0.32331848f, -0.34986877f, -0.37680054f, -0.40408325f, -0.43165588f, -0.45947266f, -0.48747253f, -0.51560974f, -0.54382324f, -0.57203674f, -0.6002197f, -0.6282959f, -0.6562195f, -0.6839142f, -0.71131897f, -0.7383728f, -0.7650299f, -0.791214f, -0.816864f, -0.84194946f, -0.8663635f, -0.89009094f, -0.9130554f, -0.9351959f, -0.95648193f, -0.9768524f, -0.99624634f, -1.0146179f, -1.0319366f, -1.0481567f, -1.0632172f, -1.0771179f, -1.0897827f, -1.1012115f, -1.1113739f, -1.120224f, -1.1277466f, -1.1339264f, -1.1387634f, -1.1422119f, -1.1442871f, 1.144989f, 1.1442871f, 1.1422119f, 1.1387634f, 1.1339264f, 1.1277466f, 1.120224f, 1.1113739f, 1.1012115f, 1.0897827f, 1.0771179f, 1.0632172f, 1.0481567f, 1.0319366f, 1.0146179f, 0.99624634f, 0.9768524f, 0.95648193f, 0.9351959f, 0.9130554f, 0.89009094f, 0.8663635f, 0.84194946f, 0.816864f, 0.791214f, 0.7650299f, 0.7383728f, 0.71131897f, 0.6839142f, 0.6562195f, 0.6282959f, 0.6002197f, 0.57203674f, 0.54382324f, 0.51560974f, 0.48747253f, 0.45947266f, 0.43165588f, 0.40408325f, 0.37680054f, 0.34986877f, 0.32331848f, 0.2972107f, 0.2715912f, 0.24650574f, 0.22198486f, 0.19805908f, 0.17478943f, 0.15220642f, 0.13031006f, 0.10916138f, 0.088775635f, 0.06916809f, 0.050354004f, 0.03237915f, 0.015228271f, -0.001068115f, -0.01651001f, -0.031082153f, -0.044784546f, -0.057617188f, -0.06959534f, -0.08068848f, -0.090927124f, 0.10031128f, 0.1088562f, 0.11657715f, 0.12347412f, 0.12957764f, 0.1348877f, 0.13945007f, 0.14326477f, 0.1463623f, 0.1487732f, 0.15049744f, 0.15159607f, 0.15206909f, 0.15196228f, 0.15130615f, 0.15011597f, 0.14842224f, 0.1462555f, 0.14367676f, 0.14067078f, 0.13729858f, 0.1335907f, 0.12956238f, 0.1252594f, 0.12069702f, 0.11592102f, 0.110946655f, 0.1058197f, 0.10054016f, 0.09516907f, 0.08970642f, 0.08418274f, 0.07862854f, 0.07305908f, 0.06752014f, 0.06199646f, 0.056533813f, 0.051132202f, 0.045837402f, 0.040634155f, 0.03555298f, 0.03060913f, 0.025817871f, 0.0211792f, 0.016708374f, 0.012420654f, 0.00831604f, 0.004394531f, 0.000686646f, -0.002822876f, -0.006134033f, -0.009231567f, -0.012115479f, -0.014801025f, -0.01725769f, -0.01953125f, -0.021575928f, -0.023422241f, -0.02508545f, -0.026535034f, -0.027801514f, -0.028884888f, -0.029785156f, -0.030517578f, 0.031082153f, 0.03147888f, 0.03173828f, 0.031845093f, 0.031814575f, 0.031661987f, 0.03138733f, 0.03100586f, 0.030532837f, 0.029937744f, 0.029281616f, 0.028533936f, 0.02772522f, 0.02684021f, 0.025909424f, 0.024932861f, 0.023910522f, 0.022857666f, 0.02178955f, 0.020690918f, 0.019577026f, 0.018463135f, 0.017349243f, 0.016235352f, 0.01512146f, 0.014022827f, 0.012939453f, 0.011886597f, 0.010848999f, 0.009841919f, 0.008865356f, 0.007919312f, 0.007003784f, 0.006118774f, 0.0052948f, 0.004486084f, 0.003723145f, 0.003005981f, 0.002334595f, 0.001693726f, 0.001098633f, 0.000549316f, 3.0518E-05f, -0.000442505f, -0.000869751f, -0.001266479f, -0.001617432f, -0.001937866f, -0.002227783f, -0.002487183f, -0.002700806f, -0.002883911f, -0.003051758f, -0.003173828f, -0.00328064f, -0.003372192f, -0.003417969f, -0.003463745f, -0.003479004f, -0.003479004f, -0.003463745f, -0.003433228f, -0.003387451f, -0.003326416f, 0.003250122f, 0.003173828f, 0.003082275f, 0.002990723f, 0.00289917f, 0.002792358f, 0.002685547f, 0.002578735f, 0.002456665f, 0.002349854f, 0.002243042f, 0.002120972f, 0.00201416f, 0.001907349f, 0.001785278f, 0.001693726f, 0.001586914f, 0.001480103f, 0.00138855f, 0.001296997f, 0.001205444f, 0.001113892f, 0.001037598f, 0.000961304f, 0.00088501f, 0.000808716f, 0.000747681f, 0.000686646f, 0.00062561f, 0.000579834f, 0.000534058f, 0.000473022f, 0.000442505f, 0.000396729f, 0.000366211f, 0.000320435f, 0.000289917f, 0.000259399f, 0.000244141f, 0.000213623f, 0.000198364f, 0.000167847f, 0.000152588f, 0.000137329f, 0.00012207f, 0.000106812f, 0.000106812f, 9.1553E-05f, 7.6294E-05f, 7.6294E-05f, 6.1035E-05f, 6.1035E-05f, 4.5776E-05f, 4.5776E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f }; private static float[] SYNTH_COS64_TABLE = new float[31] { 0.500603f, 0.5024193f, 0.50547093f, 0.5097956f, 0.5154473f, 0.5224986f, 0.5310426f, 0.5411961f, 0.5531039f, 0.56694406f, 0.582935f, 0.6013449f, 0.6225041f, 0.6468218f, 0.6748083f, 0.70710677f, 0.7445363f, 0.7881546f, 0.8393496f, 0.8999762f, 0.9725682f, 1.0606776f, 1.1694399f, 1.306563f, 1.4841646f, 1.7224472f, 2.057781f, 2.5629156f, 3.4076085f, 5.1011486f, 10.190008f }; private List<float[]> _synBuf = new List<float[]>(2); private List<int> _bufOffset = new List<int>(2); private float[] _eq; private float[] ippuv = new float[512]; private float[] ei32 = new float[16]; private float[] eo32 = new float[16]; private float[] oi32 = new float[16]; private float[] oo32 = new float[16]; private float[] ei16 = new float[8]; private float[] eo16 = new float[8]; private float[] oi16 = new float[8]; private float[] oo16 = new float[8]; private float[] ei8 = new float[4]; private float[] tmp8 = new float[6]; private float[] oi8 = new float[4]; private float[] oo8 = new float[4]; internal StereoMode StereoMode { get; set; } internal LayerDecoderBase() { StereoMode = StereoMode.Both; } internal abstract int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1); internal void SetEQ(float[] eq) { if (eq == null || eq.Length == 32) { _eq = eq; } } internal virtual void ResetForSeek() { _synBuf.Clear(); _bufOffset.Clear(); } protected void InversePolyPhase(int channel, float[] data) { GetBufAndOffset(channel, out var synBuf, out var k); if (_eq != null) { for (int i = 0; i < 32; i++) { data[i] *= _eq[i]; } } DCT32(data, synBuf, k); BuildUVec(ippuv, synBuf, k); DewindowOutput(ippuv, data); } private void GetBufAndOffset(int channel, out float[] synBuf, out int k) { while (_synBuf.Count <= channel) { _synBuf.Add(new float[1024]); } while (_bufOffset.Count <= channel) { _bufOffset.Add(0); } synBuf = _synBuf[channel]; k = _bufOffset[channel]; k = (k - 32) & 0x1FF; _bufOffset[channel] = k; } private void DCT32(float[] _in, float[] _out, int k) { for (int i = 0; i < 16; i++) { ei32[i] = _in[i] + _in[31 - i]; oi32[i] = (_in[i] - _in[31 - i]) * SYNTH_COS64_TABLE[2 * i]; } DCT16(ei32, eo32); DCT16(oi32, oo32); for (int i = 0; i < 15; i++) { _out[2 * i + k] = eo32[i]; _out[2 * i + 1 + k] = oo32[i] + oo32[i + 1]; } _out[30 + k] = eo32[15]; _out[31 + k] = oo32[15]; } private void DCT16(float[] _in, float[] _out) { float num = _in[0]; float num2 = _in[15]; ei16[0] = num + num2; oi16[0] = (num - num2) * SYNTH_COS64_TABLE[1]; num = _in[1]; num2 = _in[14]; ei16[1] = num + num2; oi16[1] = (num - num2) * SYNTH_COS64_TABLE[5]; num = _in[2]; num2 = _in[13]; ei16[2] = num + num2; oi16[2] = (num - num2) * SYNTH_COS64_TABLE[9]; num = _in[3]; num2 = _in[12]; ei16[3] = num + num2; oi16[3] = (num - num2) * SYNTH_COS64_TABLE[13]; num = _in[4]; num2 = _in[11]; ei16[4] = num + num2; oi16[4] = (num - num2) * SYNTH_COS64_TABLE[17]; num = _in[5]; num2 = _in[10]; ei16[5] = num + num2; oi16[5] = (num - num2) * SYNTH_COS64_TABLE[21]; num = _in[6]; num2 = _in[9]; ei16[6] = num + num2; oi16[6] = (num - num2) * SYNTH_COS64_TABLE[25]; num = _in[7]; num2 = _in[8]; ei16[7] = num + num2; oi16[7] = (num - num2) * SYNTH_COS64_TABLE[29]; DCT8(ei16, eo16); DCT8(oi16, oo16); _out[0] = eo16[0]; _out[1] = oo16[0] + oo16[1]; _out[2] = eo16[1]; _out[3] = oo16[1] + oo16[2]; _out[4] = eo16[2]; _out[5] = oo16[2] + oo16[3]; _out[6] = eo16[3]; _out[7] = oo16[3] + oo16[4]; _out[8] = eo16[4]; _out[9] = oo16[4] + oo16[5]; _out[10] = eo16[5]; _out[11] = oo16[5] + oo16[6]; _out[12] = eo16[6]; _out[13] = oo16[6] + oo16[7]; _out[14] = eo16[7]; _out[15] = oo16[7]; } private void DCT8(float[] _in, float[] _out) { ei8[0] = _in[0] + _in[7]; ei8[1] = _in[3] + _in[4]; ei8[2] = _in[1] + _in[6]; ei8[3] = _in[2] + _in[5]; tmp8[0] = ei8[0] + ei8[1]; tmp8[1] = ei8[2] + ei8[3]; tmp8[2] = (ei8[0] - ei8[1]) * SYNTH_COS64_TABLE[7]; tmp8[3] = (ei8[2] - ei8[3]) * SYNTH_COS64_TABLE[23]; tmp8[4] = (tmp8[2] - tmp8[3]) * 0.70710677f; _out[0] = tmp8[0] + tmp8[1]; _out[2] = tmp8[2] + tmp8[3] + tmp8[4]; _out[4] = (tmp8[0] - tmp8[1]) * 0.70710677f; _out[6] = tmp8[4]; oi8[0] = (_in[0] - _in[7]) * SYNTH_COS64_TABLE[3]; oi8[1] = (_in[1] - _in[6]) * SYNTH_COS64_TABLE[11]; oi8[2] = (_in[2] - _in[5]) * SYNTH_COS64_TABLE[19]; oi8[3] = (_in[3] - _in[4]) * SYNTH_COS64_TABLE[27]; tmp8[0] = oi8[0] + oi8[3]; tmp8[1] = oi8[1] + oi8[2]; tmp8[2] = (oi8[0] - oi8[3]) * SYNTH_COS64_TABLE[7]; tmp8[3] = (oi8[1] - oi8[2]) * SYNTH_COS64_TABLE[23]; tmp8[4] = tmp8[2] + tmp8[3]; tmp8[5] = (tmp8[2] - tmp8[3]) * 0.70710677f; oo8[0] = tmp8[0] + tmp8[1]; oo8[1] = tmp8[4] + tmp8[5]; oo8[2] = (tmp8[0] - tmp8[1]) * 0.70710677f; oo8[3] = tmp8[5]; _out[1] = oo8[0] + oo8[1]; _out[3] = oo8[1] + oo8[2]; _out[5] = oo8[2] + oo8[3]; _out[7] = oo8[3]; } private void BuildUVec(float[] u_vec, float[] cur_synbuf, int k) { int num = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 16; j++) { u_vec[num + j] = cur_synbuf[k + j + 16]; u_vec[num + j + 17] = 0f - cur_synbuf[k + 31 - j]; } k = (k + 32) & 0x1FF; for (int j = 0; j < 16; j++) { u_vec[num + j + 32] = 0f - cur_synbuf[k + 16 - j]; u_vec[num + j + 48] = 0f - cur_synbuf[k + j]; } u_vec[num + 16] = 0f; k = (k + 32) & 0x1FF; num += 64; } } private void DewindowOutput(float[] u_vec, float[] samples) { for (int i = 0; i < 512; i++) { u_vec[i] *= DEWINDOW_TABLE[i]; } for (int j = 0; j < 32; j++) { float num = u_vec[j]; num += u_vec[j + 32]; num += u_vec[j + 64]; num += u_vec[j + 96]; num += u_vec[j + 128]; num += u_vec[j + 160]; num += u_vec[j + 192]; num += u_vec[j + 224]; num += u_vec[j + 256]; num += u_vec[j + 288]; num += u_vec[j + 320]; num += u_vec[j + 352]; num += u_vec[j + 384]; num += u_vec[j + 416]; num += u_vec[j + 448]; num += u_vec[j + 480]; u_vec[j] = num; } for (int k = 0; k < 32; k++) { samples[k] = u_vec[k]; } } } internal class LayerIDecoder : LayerIIDecoderBase { private static readonly int[] _rateTable = new int[32]; private static readonly int[][] _allocLookupTable = new int[1][] { new int[17] { 4, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } }; internal static bool GetCRC(MpegFrame frame, ref uint crc) { return LayerIIDecoderBase.GetCRC(frame, _rateTable, _allocLookupTable, readScfsiBits: false, ref crc); } internal LayerIDecoder() : base(_allocLookupTable, 1) { } protected override int[] GetRateTable(IMpegFrame frame) { return _rateTable; } protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels) { } } internal class LayerIIDecoder : LayerIIDecoderBase { private static readonly int[][] _rateLookupTable = new int[5][] { new int[27] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, new int[30] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, new int[8] { 4, 4, 5, 5, 5, 5, 5, 5 }, new int[12] { 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, new int[30] { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 } }; private static readonly int[][] _allocLookupTable = new int[8][] { new int[5] { 2, 0, -5, -7, 16 }, new int[9] { 3, 0, -5, -7, 3, -10, 4, 5, 16 }, new int[17] { 4, 0, -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, new int[17] { 4, 0, -5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, new int[17] { 4, 0, -5, -7, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, new int[9] { 3, 0, -5, -7, -10, 4, 5, 6, 9 }, new int[17] { 4, 0, -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, new int[5] { 2, 0, -5, -7, 3 } }; internal static bool GetCRC(MpegFrame frame, ref uint crc) { return LayerIIDecoderBase.GetCRC(frame, SelectTable(frame), _allocLookupTable, readScfsiBits: true, ref crc); } private static int[] SelectTable(IMpegFrame frame) { int num = frame.BitRate / ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) / 1000; if (frame.Version == MpegVersion.Version1) { if ((num >= 56 && num <= 80) || (frame.SampleRate == 48000 && num >= 56)) { return _rateLookupTable[0]; } if (frame.SampleRate != 48000 && num >= 96) { return _rateLookupTable[1]; } if (frame.SampleRate != 32000 && num <= 48) { return _rateLookupTable[2]; } return _rateLookupTable[3]; } return _rateLookupTable[4]; } internal LayerIIDecoder() : base(_allocLookupTable, 3) { } protected override int[] GetRateTable(IMpegFrame frame) { return SelectTable(frame); } protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels) { for (int i = 0; i < 30; i++) { for (int j = 0; j < channels; j++) { if (scfsi[j][i] == 2) { scfsi[j][i] = frame.ReadBits(2); } } } } } internal abstract class LayerIIDecoderBase : LayerDecoderBase { protected const int SSLIMIT = 12; private static readonly float[] _groupedC = new float[5] { 0f, 0f, 1.3333334f, 1.6f, 1.7777778f }; private static readonly float[] _groupedD = new float[5] { 0f, 0f, -0.5f, -0.5f, -0.5f }; private static readonly float[] _C = new float[17] { 0f, 0f, 1.3333334f, 1.1428572f, 1.0666667f, 1.032258f, 1.0158731f, 1.007874f, 1.0039216f, 1.0019569f, 1.0009775f, 1.0004885f, 1.0002443f, 1.0001221f, 1.000061f, 1.0000305f, 1.0000153f }; private static readonly float[] _D = new float[17] { 0f, 0f, -0.5f, -0.75f, -0.875f, -0.9375f, -31f / 32f, -63f / 64f, -127f / 128f, -0.99609375f, -0.9980469f, -0.99902344f, -0.9995117f, -0.99975586f, -0.9998779f, -0.99993896f, -0.9999695f }; private static readonly float[] _denormalMultiplier = new float[64] { 2f, 1.587401f, 1.2599211f, 1f, 0.7937005f, 0.62996054f, 0.5f, 0.39685026f, 0.31498027f, 0.25f, 0.19842513f, 0.15749013f, 0.125f, 0.099212565f, 0.07874507f, 0.0625f, 0.049606282f, 0.039372534f, 1f / 32f, 0.024803141f, 0.019686267f, 1f / 64f, 0.012401571f, 0.009843133f, 1f / 128f, 0.0062007853f, 0.0049215667f, 0.00390625f, 0.0031003926f, 0.0024607833f, 0.001953125f, 0.0015501963f, 0.0012303917f, 0.0009765625f, 0.00077509816f, 0.00061519584f, 0.00048828125f, 0.00038754908f, 0.00030759792f, 0.00024414062f, 0.00019377454f, 0.00015379896f, 0.00012207031f, 9.688727E-05f, 7.689948E-05f, 6.1035156E-05f, 4.8443635E-05f, 3.844974E-05f, 3.0517578E-05f, 2.4221818E-05f, 1.922487E-05f, 1.5258789E-05f, 1.2110909E-05f, 9.612435E-06f, 7.6293945E-06f, 6.0554544E-06f, 4.8062175E-06f, 3.8146973E-06f, 3.0277272E-06f, 2.4031087E-06f, 1.9073486E-06f, 1.5138636E-06f, 1.2015544E-06f, 9.536743E-07f }; private int _channels; private int _jsbound; private int _granuleCount; private int[][] _allocLookupTable; private int[][] _scfsi; private int[][] _samples; private int[][][] _scalefac; private float[] _polyPhaseBuf; private int[][] _allocation; protected static bool GetCRC(MpegFrame frame, int[] rateTable, int[][] allocLookupTable, bool readScfsiBits, ref uint crc) { int num = 0; int num2 = rateTable.Length; int num3 = num2; if (frame.ChannelMode == MpegChannelMode.JointStereo) { num3 = frame.ChannelModeExtension * 4 + 4; } int num4 = ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2); int i; for (i = 0; i < num3; i++) { int num5 = allocLookupTable[rateTable[i]][0]; for (int j = 0; j < num4; j++) { int num6 = frame.ReadBits(num5); if (num6 > 0) { num += 2; } MpegFrame.UpdateCRC(num6, num5, ref crc); } } for (; i < num2; i++) { int num7 = allocLookupTable[rateTable[i]][0]; int num8 = frame.ReadBits(num7); if (num8 > 0) { num += num4 * 2; } MpegFrame.UpdateCRC(num8, num7, ref crc); } if (readScfsiBits) { while (num >= 2) { MpegFrame.UpdateCRC(frame.ReadBits(2), 2, ref crc); num -= 2; } } return true; } protected LayerIIDecoderBase(int[][] allocLookupTable, int granuleCount) { _allocLookupTable = allocLookupTable; _granuleCount = granuleCount; _allocation = new int[2][] { new int[32], new int[32] }; _scfsi = new int[2][] { new int[32], new int[32] }; _samples = new int[2][] { new int[384 * _granuleCount], new int[384 * _granuleCount] }; _scalefac = new int[2][][] { new int[3][], new int[3][] }; for (int i = 0; i < 3; i++) { _scalefac[0][i] = new int[32]; _scalefac[1][i] = new int[32]; } _polyPhaseBuf = new float[32]; } internal override int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1) { InitFrame(frame); int[] rateTable = GetRateTable(frame); ReadAllocation(frame, rateTable); for (int i = 0; i < _scfsi[0].Length; i++) { _scfsi[0][i] = ((_allocation[0][i] != 0) ? 2 : (-1)); _scfsi[1][i] = ((_allocation[1][i] != 0) ? 2 : (-1)); } ReadScaleFactorSelection(frame, _scfsi, _channels); ReadScaleFactors(frame); ReadSamples(frame); return DecodeSamples(ch0, ch1); } private void InitFrame(IMpegFrame frame) { switch (frame.ChannelMode) { case MpegChannelMode.Mono: _channels = 1; _jsbound = 32; break; case MpegChannelMode.JointStereo: _channels = 2; _jsbound = frame.ChannelModeExtension * 4 + 4; break; default: _channels = 2; _jsbound = 32; break; } } protected abstract int[] GetRateTable(IMpegFrame frame); private void ReadAllocation(IMpegFrame frame, int[] rateTable) { int num = rateTable.Length; if (_jsbound > num) { _jsbound = num; } Array.Clear(_allocation[0], 0, 32); Array.Clear(_allocation[1], 0, 32); int i; for (i = 0; i < _jsbound; i++) { int[] array = _allocLookupTable[rateTable[i]]; int bitCount = array[0]; for (int j = 0; j < _channels; j++) { _allocation[j][i] = array[frame.ReadBits(bitCount) + 1]; } } for (; i < num; i++) { int[] array2 = _allocLookupTable[rateTable[i]]; _allocation[0][i] = (_allocation[1][i] = array2[frame.ReadBits(array2[0]) + 1]); } } protected abstract void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels); private void ReadScaleFactors(IMpegFrame frame) { for (int i = 0; i < 32; i++) { for (int j = 0; j < _channels; j++) { switch (_scfsi[j][i]) { case 0: _scalefac[j][0][i] = frame.ReadBits(6); _scalefac[j][1][i] = frame.ReadBits(6); _scalefac[j][2][i] = frame.ReadBits(6); break; case 1: _scalefac[j][0][i] = (_scalefac[j][1][i] = frame.ReadBits(6)); _scalefac[j][2][i] = frame.ReadBits(6); break; case 2: _scalefac[j][0][i] = (_scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6))); break; case 3: _scalefac[j][0][i] = frame.ReadBits(6); _scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6)); break; default: _scalefac[j][0][i] = 63; _scalefac[j][1][i] = 63; _scalefac[j][2][i] = 63; break; } } } } private void ReadSamples(IMpegFrame frame) { int num = 0; int num2 = 0; while (num < 12) { int num3 = 0; while (num3 < 32) { for (int i = 0; i < _channels; i++) { if (i == 0 || num3 < _jsbound) { int num4 = _allocation[i][num3]; if (num4 != 0) { if (num4 < 0) { int num5 = frame.ReadBits(-num4); int num6 = (1 << -num4 / 2 + -num4 % 2 - 1) + 1; _samples[i][num2] = num5 % num6; num5 /= num6; _samples[i][num2 + 32] = num5 % num6; _samples[i][num2 + 64] = num5 / num6; } else { for (int j = 0; j < _granuleCount; j++) { _samples[i][num2 + 32 * j] = frame.ReadBits(num4); } } } else { for (int k = 0; k < _granuleCount; k++) { _samples[i][num2 + 32 * k] = 0; } } } else { for (int l = 0; l < _granuleCount; l++) { _samples[1][num2 + 32 * l] = _samples[0][num2 + 32 * l]; } } } num3++; num2++; } num++; num2 += 32 * (_granuleCount - 1); } } private int DecodeSamples(float[] ch0, float[] ch1) { float[][] array = new float[2][]; int num = 0; int num2 = _channels - 1; if (_channels == 1 || base.StereoMode == StereoMode.LeftOnly) { array[0] = ch0; num2 = 0; } else if (base.StereoMode == StereoMode.RightOnly) { array[1] = ch0; num = 1; } else { array[0] = ch0; array[1] = ch1; } int num3 = 0; for (int i = num; i <= num2; i++) { num3 = 0; for (int j = 0; j < _granuleCount; j++) { for (int k = 0; k < 12; k++) { int num4 = 0; while (num4 < 32) { int num5 = _allocation[i][num4]; if (num5 != 0) { float[] array2; float[] array3; if (num5 < 0) { num5 = -num5 / 2 + -num5 % 2 - 1; array2 = _groupedC; array3 = _groupedD; } else { array2 = _C; array3 = _D; } _polyPhaseBuf[num4] = array2[num5] * ((float)(_samples[i][num3] << 16 - num5) / 32768f + array3[num5]) * _denormalMultiplier[_scalefac[i][j][num4]]; } else { _polyPhaseBuf[num4] = 0f; } num4++; num3++; } InversePolyPhase(i, _polyPhaseBuf); Array.Copy(_polyPhaseBuf, 0, array[i], num3 - 32, 32); } } } if (_channels == 2 && base.StereoMode == StereoMode.DownmixToMono) { for (int l = 0; l < num3; l++) { ch0[l] = (ch0[l] + ch1[l]) / 2f; } } return num3; } } internal sealed class LayerIIIDecoder : LayerDecoderBase { private class HybridMDCT { private const float PI = MathF.PI; private static float[][] _swin; private static float[] icos72_table; private List<float[]> _prevBlock; private List<float[]> _nextBlock; private float[] _imdctTemp = new float[18]; private float[] _imdctResult = new float[36]; private const float sqrt32 = 0.8660254f; static HybridMDCT() { icos72_table = new float[35] { 0.50047636f, 0.5019099f, 0.5043145f, 0.5077133f, 0.51213974f, 0.5176381f, 0.5242646f, 0.5320889f, 0.5411961f, 0.55168897f, 0.56369096f, 0.57735026f, 0.59284455f, 0.61038727f, 0.6302362f, 0.65270364f, 0.67817086f, 0.70710677f, 0.7400936f, 0.7778619f, 0.8213398f, 0.8717234f, 0.9305795f, 1f, 1.0828403f, 1.1831008f, 1.306563f, 1.4619021f, 1.6627548f, 1.9318516f, 2.3101132f, 2.8793852f, 3.830649f, 5.7368565f, 11.462792f }; _swin = new float[4][] { new float[36], new float[36], new float[36], new float[36] }; for (int i = 0; i < 36; i++) { _swin[0][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 0; i < 18; i++) { _swin[1][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 18; i < 24; i++) { _swin[1][i] = 1f; } for (int i = 24; i < 30; i++) { _swin[1][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5 - 18.0)); } for (int i = 30; i < 36; i++) { _swin[1][i] = 0f; } for (int i = 0; i < 6; i++) { _swin[3][i] = 0f; } for (int i = 6; i < 12; i++) { _swin[3][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5 - 6.0)); } for (int i = 12; i < 18; i++) { _swin[3][i] = 1f; } for (int i = 18; i < 36; i++) { _swin[3][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 0; i < 12; i++) { _swin[2][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5)); } for (int i = 12; i < 36; i++) { _swin[2][i] = 0f; } } internal HybridMDCT() { _prevBlock = new List<float[]>(); _nextBlock = new List<float[]>(); } internal void Reset() { _prevBlock.Clear(); _nextBlock.Clear(); } private void GetPrevBlock(int channel, out float[] prevBlock, out float[] nextBlock) { while (_prevBlock.Count <= channel) { _prevBlock.Add(new float[576]); } while (_nextBlock.Count <= channel) { _nextBlock.Add(new float[576]); } prevBlock = _prevBlock[channel]; nextBlock = _nextBlock[channel]; _nextBlock[channel] = prevBlock; _prevBlock[channel] = nextBlock; } internal void Apply(float[] fsIn, int channel, int blockType, bool doMixed) { GetPrevBlock(channel, out var prevBlock, out var nextBlock); int sbStart = 0; if (doMixed) { LongImpl(fsIn, 0, 2, nextBlock, 0); sbStart = 2; } if (blockType == 2) { ShortImpl(fsIn, sbStart, nextBlock); } else { LongImpl(fsIn, sbStart, 32, nextBlock, blockType); } for (int i = 0; i < 576; i++) { fsIn[i] += prevBlock[i]; } } private void LongImpl(float[] fsIn, int sbStart, int sbLimit, float[] nextblck, int blockType) { int i = sbStart; int num = sbStart * 18; for (; i < sbLimit; i++) { Array.Copy(fsIn, num, _imdctTemp, 0, 18); LongIMDCT(_imdctTemp, _imdctResult); float[] array = _swin[blockType]; int j; for (j = 0; j < 18; j++) { fsIn[num++] = _imdctResult[j] * array[j]; } num -= 18; for (; j < 36; j++) { nextblck[num++] = _imdctResult[j] * array[j]; } } } private static void LongIMDCT(float[] invec, float[] outvec) { float[] array = new float[17]; float[] array2 = new float[18]; float[] array3 = new float[9]; float[] array4 = new float[9]; float[] array5 = new float[9]; float[] array6 = new float[9]; int i; for (i = 0; i < 17; i++) { array[i] = invec[i] + invec[i + 1]; } array3[0] = invec[0]; array4[0] = array[0]; int num = 0; i = 1; while (i < 9) { array3[i] = array[num + 1]; array4[i] = array[num] + array[num + 2]; i++; num += 2; } imdct_9pt(array3, array5); imdct_9pt(array4, array6); for (i = 0; i < 9; i++) { array6[i] *= ICOS36_A(i); array2[i] = (array5[i] + array6[i]) * ICOS72_A(i); } for (; i < 18; i++) { array2[i] = (array5[17 - i] - array6[17 - i]) * ICOS72_A(i); } outvec[0] = array2[9]; outvec[1] = array2[10]; outvec[2] = array2[11]; outvec[3] = array2[12]; outvec[4] = array2[13]; outvec[5] = array2[14]; outvec[6] = array2[15]; outvec[7] = array2[16]; outvec[8] = array2[17]; outvec[9] = 0f - array2[17]; outvec[10] = 0f - array2[16]; outvec[11] = 0f - array2[15]; outvec[12] = 0f - array2[14]; outvec[13] = 0f - array2[13]; outvec[14] = 0f - array2[12]; outvec[15] = 0f - array2[11]; outvec[16] = 0f - array2[10]; outvec[17] = 0f - array2[9]; outvec[35] = (outvec[18] = 0f - array2[8]); outvec[34] = (outvec[19] = 0f - array2[7]); outvec[33] = (outvec[20] = 0f - array2[6]); outvec[32] = (outvec[21] = 0f - array2[5]); outvec[31] = (outvec[22] = 0f - array2[4]); outvec[30] = (outvec[23] = 0f - array2[3]); outvec[29] = (outvec[24] = 0f - array2[2]); outvec[28] = (outvec[25] = 0f - array2[1]); outvec[27] = (outvec[26] = 0f - array2[0]); } private static float ICOS72_A(int i) { return icos72_table[2 * i]; } private static float ICOS36_A(int i) { return icos72_table[4 * i + 1]; } private static void imdct_9pt(float[] invec, float[] outvec) { float[] array = new float[5]; float[] array2 = new float[4]; float num = invec[6] / 2f + invec[0]; float num2 = invec[0] - invec[6]; float num3 = invec[2] - invec[4] - invec[8]; array[0] = num + invec[2] * 0.9396926f + invec[4] * 0.76604444f + invec[8] * 0.17364818f; array[1] = num3 / 2f + num2; array[2] = num - invec[2] * 0.17364818f - invec[4] * 0.9396926f + invec[8] * 0.76604444f; array[3] = num - invec[2] * 0.76604444f + invec[4] * 0.17364818f - invec[8] * 0.9396926f; array[4] = num2 - num3; float num4 = invec[1] + invec[3]; float num5 = invec[3] + invec[5]; num = (invec[5] + invec[7]) * 0.5f + invec[1]; array2[0] = num + num4 * 0.9396926f + num5 * 0.76604444f; array2[1] = (invec[1] - invec[5]) * 1.5f - invec[7]; array2[2] = num - num4 * 0.17364818f - num5 * 0.9396926f; array2[3] = num - num4 * 0.76604444f + num5 * 0.17364818f; array2[0] += invec[7] * 0.17364818f; array2[1] -= invec[7] * 0.5f; array2[2] += invec[7] * 0.76604444f; array2[3] -= invec[7] * 0.9396926f; array2[0] *= 0.5077133f; array2[1] *= 0.57735026f; array2[2] *= 0.7778619f; array2[3] *= 1.4619021f; for (int i = 0; i < 4; i++) { outvec[i] = array[i] + array2[i]; } outvec[4] = array[4]; for (int i = 5; i < 9; i++) { outvec[i] = array[8 - i] - array2[8 - i]; } } private void ShortImpl(float[] fsIn, int sbStart, float[] nextblck) { _ = _swin[2]; int num = sbStart; int num2 = sbStart * 18; while (num < 32) { int i = 0; int num3 = 0; for (; i < 3; i++) { int num4 = num2 + i; for (int j = 0; j < 6; j++) { _imdctTemp[num3 + j] = fsIn[num4]; num4 += 3; } num3 += 6; } Array.Clear(fsIn, num2, 6); ShortIMDCT(_imdctTemp, 0, _imdctResult); Array.Copy(_imdctResult, 0, fsIn, num2 + 6, 12); ShortIMDCT(_imdct