Decompiled source of Skins v0.12.0

Skins.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Compression;
using System.Linq;
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.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using CellMenu;
using Clonesoft.Json;
using Clonesoft.Json.Linq;
using Clonesoft.Json.Serialization;
using FluffyUnderware.DevTools.Extensions;
using GameData;
using Gear;
using Globals;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Localization;
using MTFO.API;
using Microsoft.CodeAnalysis;
using Player;
using Skins.Assets;
using Skins.Config;
using Skins.Data;
using Skins.Icons;
using Skins.Interop;
using Skins.Localization;
using Skins.Manifest;
using Skins.Meshes;
using Skins.Patches;
using Skins.Target;
using Skins.Textures;
using Skins.UI;
using Skins.UI.Menu;
using Skins.UI.Utils;
using Skins.Utils;
using Skins.Utils.Ext;
using StbDxtSharp;
using StbImageSharp;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Skins")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Skins")]
[assembly: AssemblyTitle("Skins")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Skins
{
	[HarmonyPatch]
	public class Events
	{
		public static event Action? OnGameDataInitialized;

		public static event Action<Item>? OnGearSpawnComplete;

		public static event Action? OnElevatorStop;

		public static event Action? OnBuilderDone;

		[HarmonyPatch(typeof(GameDataInit), "Initialize")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Postfix__GameDataInit_Initialize()
		{
			Events.OnGameDataInitialized?.Invoke();
		}

		[HarmonyPatch(typeof(Item), "OnGearSpawnComplete")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Postfix__Item_OnGearSpawnComplete(Item __instance)
		{
			Events.OnGearSpawnComplete?.Invoke(__instance);
		}

		[HarmonyPatch(typeof(ItemEquippable), "OnGearSpawnComplete")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Postfix__ItemEquippable_OnGearSpawnComplete(Item __instance)
		{
			Events.OnGearSpawnComplete?.Invoke(__instance);
		}

		[HarmonyPatch(typeof(GS_StopElevatorRide), "Enter")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		public static void Postfix__GS_StopElevatorRide_Enter()
		{
			Events.OnElevatorStop?.Invoke();
		}

		[HarmonyPatch(typeof(Builder), "OnFactoryDone")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		public static void Postfix__Builder_OnFactoryDone()
		{
			Events.OnBuilderDone?.Invoke();
		}
	}
	internal static class Logger
	{
		private static ManualLogSource _mLogSource;

		public static bool Ready => _mLogSource != null;

		public static void Setup()
		{
			_mLogSource = Logger.CreateLogSource("io.takina.gtfo.Skins");
		}

		public static void SetupFromInit(ManualLogSource logSource)
		{
			_mLogSource = logSource;
		}

		private static string Format(object data)
		{
			return data.ToString();
		}

		public static void Debug(object msg)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogDebug((object)Format(msg));
			}
		}

		public static void Debugf(string fmt, params object[] args)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogDebug((object)Format(string.Format(fmt, args)));
			}
		}

		public static void Info(object msg)
		{
			_mLogSource.LogInfo((object)Format(msg));
		}

		public static void Infof(string fmt, params object[] args)
		{
			_mLogSource.LogInfo((object)Format(string.Format(fmt, args)));
		}

		public static void Warn(object msg)
		{
			_mLogSource.LogWarning((object)Format(msg));
		}

		public static void Warnf(string fmt, params object[] args)
		{
			_mLogSource.LogWarning((object)Format(string.Format(fmt, args)));
		}

		public static void Error(object msg)
		{
			_mLogSource.LogError((object)Format(msg));
		}

		public static void Errorf(string fmt, params object[] args)
		{
			_mLogSource.LogError((object)Format(string.Format(fmt, args)));
		}

		public static void Fatal(object msg)
		{
			_mLogSource.LogFatal((object)Format(msg));
		}

		public static void Fatalf(string fmt, params object[] args)
		{
			_mLogSource.LogFatal((object)Format(string.Format(fmt, args)));
		}
	}
	[BepInPlugin("io.takina.gtfo.Skins", "Skins", "0.12.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		public const string NAME = "Skins";

		public const string GUID = "io.takina.gtfo.Skins";

		public const string VERSION = "0.12.0";

		internal const string GUID_MTFO = "com.dak.MTFO";

		internal const string GUID_LEGACY_LOBBY = "dev.aurirex.gtfo.legacylobby";

		public static GameObject? PluginObject;

		public static SkinProcess? UnityBehaviourProcess;

		public event Action? OnManagersSetup;

		public override void Load()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			Logger.Setup();
			Logger.Info("Skins [io.takina.gtfo.Skins @ 0.12.0]");
			JObject.Parse("{}");
			ConfigMgr.Process();
			ModData.Initialize();
			if (!PersistentConfig<UserConfig>.Load())
			{
				Logger.Fatal("Failed to load user config, aborting plugin load. Please ensure the config file is valid JSON");
				return;
			}
			Events.OnGameDataInitialized += Loc.InsertToGtfoDB;
			GearDump.Load();
			Application.quitting += Action.op_Implicit((Action)GearDump.FlushNow);
			MeshDump.Load();
			Application.quitting += Action.op_Implicit((Action)MeshDump.FlushNow);
			ShaderRefs.Preload();
			InternalData.Write();
			SkinManager.Initialize().RunSync();
			RegisterIl2CppTypes();
			OnManagersSetup += Initialize;
			Global.OnAllManagersSetup += Action.op_Implicit(this.OnManagersSetup);
			Logger.Info("Patching...");
			ApplyPatches(new Harmony("io.takina.gtfo.Skins"));
			Logger.Info("Finished Patching");
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void ApplyPatches(Harmony h)
		{
			ApplyPatch<Events>(h);
			ApplyPatch<GearPatches>(h);
			ApplyPatch<GearIconPatches>(h);
			ApplyPatch<GearIcons>(h);
			ApplyPatch<ShellSkinning>(h);
			ApplyPatch<UIManager>(h);
			ApplyPatch<UISettings>(h);
			h.PatchAll(typeof(Loc));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void ApplyPatchIfLoaded<T>(Harmony h, string guid)
		{
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(guid))
			{
				ApplyPatch<T>(h);
				Logger.Info("Applied compat patches for plugin with GUID " + guid + ".");
			}
			else
			{
				Logger.Info("Plugin with GUID " + guid + " not found, skipping compat patches for it.");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void ApplyPatch<T>(Harmony h)
		{
			h.PatchAll(typeof(T));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void RegisterIl2CppTypes()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttribute<RegisterIl2CppAttribute>() != null)
				{
					ClassInjector.RegisterTypeInIl2Cpp(type);
				}
			}
		}

		private void Initialize()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Logger.Debug("Initializing...");
			_ = Loc.CurrentLocale;
			UIManager.Initialize();
			PluginObject = new GameObject("io.takina.gtfo.Skins");
			Object.DontDestroyOnLoad((Object)(object)PluginObject);
			UnityBehaviourProcess = PluginObject.AddComponent<SkinProcess>();
			new GameObject().AddComponent<DevUI>();
		}
	}
	public static class SkinManager
	{
		public static readonly List<InventorySlot> OfflineGearInventorySlots;

		private static readonly Dictionary<int, ManagedGroupTarget> GroupTargets;

		private static readonly Dictionary<int, ManagedMaterialTarget> MaterialTargets;

		private static readonly Dictionary<string, SkinGroup> SkinGroups;

		private static bool _inReload;

		public static bool Initialized { get; private set; }

		public static bool InReload => _inReload;

		public static IEnumerable<SkinGroup> AllGroups => SkinGroups.Values;

		static SkinManager()
		{
			OfflineGearInventorySlots = new List<InventorySlot>
			{
				(InventorySlot)1,
				(InventorySlot)2,
				(InventorySlot)3,
				(InventorySlot)10,
				(InventorySlot)11
			};
			Initialized = false;
			GroupTargets = new Dictionary<int, ManagedGroupTarget>();
			MaterialTargets = new Dictionary<int, ManagedMaterialTarget>();
			SkinGroups = new Dictionary<string, SkinGroup>();
			_inReload = false;
			Events.OnBuilderDone += RegisterPlayerBackpackTargets;
		}

		public static IEnumerator Initialize()
		{
			if (Initialized)
			{
				Logger.Warn("[SkinManager] Already initialized, skipping initialization.");
				yield break;
			}
			Logger.Info("[SkinManager] Started initialization.");
			Stopwatch loadTimer = Stopwatch.StartNew();
			TextureLibrary.ResetStats();
			if (!ConfigMgr.DevEnables(eDevOpts.NoNormalize))
			{
				NormalizeFolder(ModData.SkinsFolder);
				NormalizeFolder(ModData.PerProfileSkinsFolder);
			}
			if (!ConfigMgr.DevEnables(eDevOpts.NoMove))
			{
				MoveSkinGroups(ModData.PerProfileSkinsFolder, ModData.SkinsFolder);
			}
			yield return SkinPackageManager.InstallAll();
			RegisterGroup(SkinGroup.Vanilla);
			yield return LoadSkinsFolder(ModData.SkinsFolder);
			yield return LoadSkinsFolder(ModData.PerProfileSkinsFolder);
			double manifestMs = loadTimer.Elapsed.TotalMilliseconds;
			yield return WaitForTextures();
			Initialized = true;
			string value = (ConfigMgr.DevEnables(eDevOpts.NoCompress) ? "off" : "on");
			string text = (ConfigMgr.DevEnables(eDevOpts.LegacyLoad) ? "legacy (Unity LoadImage/Compress, main thread)" : $"managed pipeline, {TextureLoader.MaxWorkers} workers");
			text += $"; load mode {ConfigMgr.SkinLoadMode}, unload {ConfigMgr.SkinUnloadMode}";
			Logger.Info($"[SkinManager] Initialization complete in {loadTimer.Elapsed.TotalMilliseconds:F0} ms (manifests {manifestMs:F0} ms, textures {loadTimer.Elapsed.TotalMilliseconds - manifestMs:F0} ms wall): {SkinGroups.Count - 1} skin group(s), {TextureLibrary.LoadedCount} texture(s) ({(double)TextureLibrary.BytesRead / 1024.0 / 1024.0:F1} MB on disk, ~{(double)TextureLibrary.EstimatedVramBytes / 1024.0 / 1024.0:F0} MB in VRAM); decode {TextureLibrary.DecodeMs:F0} ms + compress {TextureLibrary.CompressMs:F0} ms (summed across threads), upload {TextureLibrary.UploadMs:F0} ms (main thread); loader: {text}; compression {value}, {TextureLibrary.CompressedCount} compressed");
		}

		private static IEnumerator WaitForTextures()
		{
			int total = TextureLoader.Pending;
			if (total == 0)
			{
				yield break;
			}
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: true);
			}
			while (TextureLoader.Pending > 0)
			{
				TextureLoader.Pump(_inReload ? 8 : 0);
				if (TextureLoader.Pending == 0)
				{
					break;
				}
				if (_inReload)
				{
					int num = total - TextureLoader.Pending;
					DevUI.Instance?.SetCenterDisplayText($"{Loc.T("settings.reloading")}\n<size=24>textures</size>\n<b>{num}/{total}</b>");
					DevUI.Instance?.SetCenterDisplayProgress((float)num / (float)total);
					yield return null;
				}
				else
				{
					Thread.Sleep(1);
				}
			}
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: false);
			}
		}

		private static IEnumerator LoadSkinsFolder(string path)
		{
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: true);
				yield return null;
			}
			List<string> files = FileUtils.FileInEachSubdirectory(path, "manifest.skingroup.json").ToList();
			int fileCount = files.Count;
			int i = 0;
			while (i < fileCount)
			{
				if (UpdateProgress(i, fileCount))
				{
					yield return null;
				}
				string text = files[i];
				Stopwatch stopwatch = Stopwatch.StartNew();
				SkinGroup skinGroup = JsonUtils.DeserializeFromFile<SkinGroup>(text);
				if (skinGroup == null)
				{
					Logger.Warn("[SkinManager] group manifest at '" + text + "' deserialized to null, skipping.");
				}
				else if (skinGroup.Initialize(text))
				{
					RegisterGroup(skinGroup);
					Logger.Info($"[SkinManager] Loaded skin group '{skinGroup.Name}' in {stopwatch.Elapsed.TotalMilliseconds:F0} ms.");
				}
				else
				{
					Logger.Error($"[SkinManager] Failed to initialize skin group '{skinGroup.Name}' at '{text}', skipping.");
				}
				int num = i + 1;
				i = num;
			}
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: false);
			}
			bool UpdateProgress(int current, int total)
			{
				if (!_inReload)
				{
					return false;
				}
				string centerDisplayText = $"{Loc.T("settings.reloading")}\n<size=24>{path}</size>\n<b>{current + 1}/{total}</b>";
				DevUI.Instance?.SetCenterDisplayText(centerDisplayText);
				DevUI.Instance?.SetCenterDisplayProgress((float)current / (float)total);
				return true;
			}
		}

		private static void NormalizeFolder(string path)
		{
			if (!Directory.Exists(path))
			{
				return;
			}
			string[] directories = Directory.GetDirectories(path);
			foreach (string text in directories)
			{
				string text2 = Path.Combine(text, "manifest.skingroup.json");
				if (!File.Exists(text2))
				{
					Logger.Debug("[SkinManager] NormalizeFolder: no manifest found in '" + text + "', skipping.");
					continue;
				}
				SkinGroup skinGroup = JsonUtils.DeserializeFromFile<SkinGroup>(text2);
				if (skinGroup == null || string.IsNullOrEmpty(skinGroup.Guid))
				{
					Logger.Warn("[SkinManager] NormalizeFolder: could not read a valid GUID from '" + text2 + "', skipping.");
					continue;
				}
				string fileName = Path.GetFileName(text);
				if (string.Equals(fileName, skinGroup.Guid, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				string text3 = Path.Combine(path, skinGroup.Guid);
				if (Directory.Exists(text3))
				{
					Logger.Warn($"[SkinManager] NormalizeFolder: cannot rename '{fileName}' -> '{skinGroup.Guid}' -- a folder with that name already exists. Skipping.");
					continue;
				}
				try
				{
					Directory.Move(text, text3);
					Logger.Info($"[SkinManager] NormalizeFolder: renamed '{fileName}' -> '{skinGroup.Guid}'");
				}
				catch (Exception ex)
				{
					Logger.Error($"[SkinManager] NormalizeFolder: failed to rename '{fileName}' -> '{skinGroup.Guid}': {ex.Message}");
				}
			}
		}

		internal static void MoveSkinGroups(string from, string to, string callerTag = "AutoMove")
		{
			if (!Directory.Exists(from))
			{
				return;
			}
			string[] directories = Directory.GetDirectories(from);
			foreach (string text in directories)
			{
				string fileName = Path.GetFileName(text);
				string text2 = Path.Combine(to, fileName);
				if (Directory.Exists(text2))
				{
					try
					{
						Directory.Delete(text2, recursive: true);
						Logger.Info($"[SkinManager] {callerTag}: removed old global copy of '{fileName}'.");
					}
					catch (Exception ex)
					{
						Logger.Error($"[SkinManager] {callerTag}: failed to remove existing '{fileName}' from global skins folder, skipping move: {ex.Message}");
						continue;
					}
				}
				try
				{
					FileUtils.MoveDirectory(text, text2);
					Logger.Info("[SkinManager] AutoMove: moved '" + fileName + "' to global skins folder.");
				}
				catch (Exception ex2)
				{
					Logger.Error("[SkinManager] AutoMove: failed to move '" + fileName + "': " + ex2.Message);
				}
			}
		}

		public static void ApplyGroupToTargetsUnder(SkinGroup group, GameObject root, object owner)
		{
			foreach (MeshRenderer componentsInChild in root.GetComponentsInChildren<MeshRenderer>())
			{
				ApplyGroupToRawTarget(group, componentsInChild, owner);
			}
		}

		public static void ReleaseOwner(object owner)
		{
			TextureLibrary.ReleaseOwner(owner);
			MeshLibrary.ReleaseOwner(owner);
		}

		public static void SweepIdle()
		{
			if (ConfigMgr.SkinLoadMode != eSkinLoadMode.Eager)
			{
				float idleSeconds = ((ConfigMgr.SkinUnloadMode == eSkinUnloadMode.Immediate) ? 0f : ((float)ConfigMgr.UnloadIdleSeconds));
				int num = TextureLibrary.SweepIdle(idleSeconds);
				int num2 = MeshLibrary.SweepIdle(idleSeconds);
				if (num + num2 > 0)
				{
					Logger.Info($"[SkinManager] Freed {num} idle texture(s) and {num2} idle mesh(es); resident: {TextureLibrary.ResidentCount} texture(s) (~{(double)TextureLibrary.ResidentVramBytes / 1024.0 / 1024.0:F0} MB), {MeshLibrary.ResidentCount} mesh(es)");
				}
			}
		}

		public static void ApplyGroupToRawTarget(SkinGroup group, MeshRenderer meshRenderer, object owner)
		{
			Material material = ((Renderer)meshRenderer).material;
			MeshFilter component = ((Component)meshRenderer).GetComponent<MeshFilter>();
			string cleanName = NameUtils.GetCleanName(((Object)material).name);
			string text = (((Object)(object)component == (Object)null) ? null : NameUtils.GetCleanName(((Object)component.sharedMesh).name));
			MaterialSnapshot materialSnapshot = MaterialSnapshot.Capture(material);
			Dictionary<string, string> textureNames = materialSnapshot.GetTextureNames();
			materialSnapshot.Release();
			if (text != null && group.TryGetMeshTarget(text, cleanName, out MeshTarget targetOut))
			{
				Mesh val = targetOut.Acquire(owner);
				if ((Object)(object)val != (Object)null)
				{
					component.sharedMesh = val;
				}
			}
			if (!group.TryGetMaterialTarget(cleanName, textureNames, out MaterialTarget targetOut2))
			{
				Logger.Debug($"[ApplyGroupToRawTarget] skin group '{group.Name}' does not have a matching material target for material '{cleanName}' with the required textures.");
				return;
			}
			if (targetOut2.Shader != null && targetOut2.Shader != ((Object)material.shader).name)
			{
				Shader val2 = ShaderRefs.Get(targetOut2.Shader);
				if ((Object)(object)val2 == (Object)null)
				{
					Logger.Warn($"[ManagedMaterialTarget] failed to load shader '{targetOut2.Shader}' for material target '{targetOut2.MaterialNameToMatch}' in skin group '{group.Name}'. Shader will not be substituted.");
				}
				else
				{
					material.shader = val2;
				}
			}
			foreach (var (propertyName, materialProperty2) in targetOut2.Properties)
			{
				materialProperty2?.Apply(material, propertyName, owner);
			}
		}

		public static void UpdateTargetsUnder(GameObject go)
		{
			foreach (ManagedMaterialTarget componentsInChild in go.GetComponentsInChildren<ManagedMaterialTarget>())
			{
				componentsInChild.UpdateMaterial();
			}
		}

		public static void UpdateTargetsUnder(GameObject go, string groupGuid)
		{
			foreach (ManagedMaterialTarget componentsInChild in go.GetComponentsInChildren<ManagedMaterialTarget>())
			{
				componentsInChild.UpdateMaterial(overrideGroup: true, groupGuid);
			}
		}

		public static void UpdateAllTargets()
		{
			foreach (ManagedMaterialTarget value in MaterialTargets.Values)
			{
				if (!((Object)(object)value == (Object)null))
				{
					value.UpdateMaterial();
				}
			}
		}

		public static void UpdateAllGroups()
		{
			foreach (ManagedGroupTarget value in GroupTargets.Values)
			{
				if (!((Object)(object)value == (Object)null))
				{
					value.UpdateTargets();
				}
			}
		}

		internal static void RegisterPlayerBackpackTargets()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			BackpackItem val = default(BackpackItem);
			foreach (InventorySlot offlineGearInventorySlot in OfflineGearInventorySlots)
			{
				if (!PlayerBackpackManager.LocalBackpack.TryGetBackpackItem(offlineGearInventorySlot, ref val))
				{
					continue;
				}
				Item component = ((Component)val.Instance).GetComponent<Item>();
				if ((Object)(object)component == (Object)null)
				{
					Logger.Debug("[SkinManager] RegisterPlayerBackpackTargets: no Item component found on backpack item in slot " + $"{offlineGearInventorySlot}, skipping ManagedGroupTarget setup for this item.");
					continue;
				}
				ManagedGroupTarget orAddComponent = ((Component)component).gameObject.GetOrAddComponent<ManagedGroupTarget>();
				if ((Object)(object)orAddComponent == (Object)null)
				{
					Logger.Error("[SkinManager] RegisterPlayerBackpackTargets: failed to add ManagedGroupTarget component to backpack item in slot " + $"{offlineGearInventorySlot}, skipping ManagedGroupTarget setup for this item.");
				}
				else if (!((Object)(object)orAddComponent.BulletWeapon == (Object)null))
				{
					BulletWeapon bulletWeapon = orAddComponent.BulletWeapon;
					if (GearUtils.TryGetOfflineGearId(((ItemEquippable)bulletWeapon).GearIDRange, out var gearId) && ((ItemEquippable)bulletWeapon).ShellCasingData != null)
					{
						ShellSkinning.SetupPoolForGear(gearId, ((ItemEquippable)bulletWeapon).ShellCasingData.ShellCasingType);
					}
				}
			}
		}

		public static IEnumerator Reload()
		{
			if (_inReload)
			{
				Logger.Warn("[SkinManager] Already reloading!");
				yield break;
			}
			_inReload = true;
			try
			{
				GearIcons.BeforeReload();
				Unload();
				yield return Initialize();
				UpdateAllTargets();
				ShellSkinning.RebuildPools();
				GearIcons.OnSkinsReloaded();
			}
			finally
			{
				_inReload = false;
				DevUI.Instance?.SetCenterDisplayActive(active: false);
			}
		}

		public static void Unload()
		{
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: true);
				DevUI.Instance?.SetCenterDisplayText("Unloading Assets...");
			}
			SkinGroups.Clear();
			TextureLoader.CancelAll();
			TextureLibrary.UnloadAll();
			TextureMacro.UnloadAll();
			MeshLibrary.UnloadAll();
			Initialized = false;
			if (_inReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: false);
			}
		}

		public static bool TryGetGroup(string guid, [NotNullWhen(true)] out SkinGroup? group)
		{
			return SkinGroups.TryGetValue(guid, out group);
		}

		public static List<SkinGroup> GetAllMatchingGroups(TargetContext ctx)
		{
			List<SkinGroup> list = new List<SkinGroup>();
			Logger.Debug($"[SkinManager] GetAllMatchingGroups => {ctx}");
			foreach (SkinGroup value in SkinGroups.Values)
			{
				if (value.IsMatch(ctx))
				{
					list.Add(value);
					Logger.Debug($"[SkinManager] GetAllMatchingGroups => MATCH '{value.Name}' ({value.Guid})");
				}
			}
			return list;
		}

		public static SkinGroup? GetCurrentSkinGroupOfGear(uint gearPersistentId)
		{
			if (!GameDataBlockBase<PlayerOfflineGearDataBlock>.HasBlock(gearPersistentId))
			{
				return null;
			}
			if (PersistentConfig<UserConfig>.Instance == null)
			{
				return null;
			}
			if (PersistentConfig<UserConfig>.Instance.CurrentSkinConfig.OfflineGear.TryGetValue(gearPersistentId, out string value))
			{
				if (SkinGroups.TryGetValue(value, out SkinGroup value2))
				{
					return value2;
				}
				PersistentConfig<UserConfig>.Instance.CurrentSkinConfig.OfflineGear[gearPersistentId] = "10chambers.vanilla";
				PersistentConfig<UserConfig>.Save();
			}
			return SkinGroup.Vanilla;
		}

		public static SkinGroup? GetAnyMatchingGroup(TargetContext ctx)
		{
			foreach (SkinGroup value in SkinGroups.Values)
			{
				if (value.IsMatch(ctx))
				{
					return value;
				}
			}
			return null;
		}

		private static bool RegisterGroup(SkinGroup group)
		{
			if (string.IsNullOrEmpty(group.Guid))
			{
				Logger.Error($"Failed to register skin group '{group.Name}' because it has an empty guid.");
				return false;
			}
			if (!SkinGroups.TryAdd(group.Guid, group))
			{
				Logger.Warn($"Unable to register skin group '{group.Name}' ({group.Guid}) because a group with the same guid already exists. Skipping.");
				return false;
			}
			return true;
		}

		internal static void RegisterGroupTarget(ManagedGroupTarget target)
		{
			GroupTargets.Add(((Object)target).GetInstanceID(), target);
		}

		internal static void UnregisterGroupTarget(ManagedGroupTarget target)
		{
			GroupTargets.Remove(((Object)target).GetInstanceID());
		}

		internal static void RegisterMatTarget(ManagedMaterialTarget target)
		{
			MaterialTargets.Add(((Object)target).GetInstanceID(), target);
		}

		internal static void UnregisterMatTarget(ManagedMaterialTarget target)
		{
			MaterialTargets.Remove(((Object)target).GetInstanceID());
		}
	}
	public class SkinPackageManager
	{
		public const string SkinPackageExtension = ".skinspkg";

		public static IEnumerator InstallAll()
		{
			List<string> pkgFiles = FileUtils.FilesWithExtension(ModData.SkinsFolder, ".skinspkg").ToList();
			int pkgFileCount = pkgFiles.Count;
			if (pkgFileCount == 0)
			{
				yield break;
			}
			if (SkinManager.InReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: true);
				yield return null;
			}
			for (int i = 0; i < pkgFileCount; i++)
			{
				string pkgFile = pkgFiles[i];
				if (UpdateProgress(i, pkgFileCount, Path.GetFileName(pkgFile), Loc.T("settings.install.unpack")))
				{
					yield return null;
				}
				if (!Unpack(pkgFile))
				{
					Logger.Error("[SkinPackageManager] InstallAll: failed to unpack package '" + pkgFile + "'.");
					continue;
				}
				if (UpdateProgress(i, pkgFileCount, Path.GetFileName(pkgFile), Loc.T("settings.install.normalize")))
				{
					yield return null;
				}
				StagingNormalize(ModData.SkinsStagingFolder);
				string[] stagingGroups = (Directory.Exists(ModData.SkinsStagingFolder) ? Directory.GetDirectories(ModData.SkinsStagingFolder) : Array.Empty<string>());
				if (stagingGroups.Length == 0)
				{
					Logger.Error("[SkinPackageManager] InstallAll: package '" + Path.GetFileName(pkgFile) + "' contained no valid skin groups after normalization, skipping.");
					continue;
				}
				if (UpdateProgress(i, pkgFileCount, Path.GetFileName(pkgFile), Loc.T("settings.install.move")))
				{
					yield return null;
				}
				SkinManager.MoveSkinGroups(ModData.SkinsStagingFolder, ModData.SkinsFolder);
				Logger.Info($"[SkinPackageManager] InstallAll: successfully installed package '{pkgFile}' with {stagingGroups.Length} skin groups.");
				try
				{
					File.Delete(pkgFile);
				}
				catch (Exception ex)
				{
					Logger.Error("[SkinPackageManager] InstallAll: failed to delete package file '" + pkgFile + "' after installation: " + ex.Message);
				}
			}
			CleanupStagingArea();
			if (SkinManager.InReload)
			{
				DevUI.Instance?.SetCenterDisplayActive(active: false);
			}
			static bool UpdateProgress(int completed, int total, string processing, string message)
			{
				if (!SkinManager.InReload)
				{
					return false;
				}
				string centerDisplayText = $"{Loc.T("settings.installing")}\n<size=24>{processing}</size>\n<b>{completed + 1}/{total}</b>{(string.IsNullOrWhiteSpace(message) ? "" : (" " + message))}";
				DevUI.Instance?.SetCenterDisplayText(centerDisplayText);
				DevUI.Instance?.SetCenterDisplayProgress((float)completed / (float)total);
				return true;
			}
		}

		private static bool SetupStagingArea()
		{
			try
			{
				Directory.CreateDirectory(ModData.SkinsStagingFolder);
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("[SkinPackageManager] SetupStagingArea: failed to create staging directory '" + ModData.SkinsStagingFolder + "': " + ex.Message);
				return false;
			}
		}

		private static bool CleanupStagingArea()
		{
			if (!Directory.Exists(ModData.SkinsStagingFolder))
			{
				return true;
			}
			try
			{
				Directory.Delete(ModData.SkinsStagingFolder, recursive: true);
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("[SkinPackageManager] CleanupStagingArea: failed to clear staging directory '" + ModData.SkinsStagingFolder + "': " + ex.Message);
				return false;
			}
		}

		private static bool Unpack(string packageFile)
		{
			if (!CleanupStagingArea())
			{
				return false;
			}
			if (!SetupStagingArea())
			{
				return false;
			}
			try
			{
				ZipFile.ExtractToDirectory(packageFile, ModData.SkinsStagingFolder);
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("[SkinPackageManager] Unpack: failed to unpack package '" + packageFile + "': " + ex.Message);
				return false;
			}
		}

		private static void StagingNormalize(string folderPath)
		{
			if (!Directory.Exists(folderPath))
			{
				return;
			}
			string[] directories = Directory.GetDirectories(folderPath);
			foreach (string text in directories)
			{
				string text2 = Path.Combine(text, "manifest.skingroup.json");
				if (!File.Exists(text2))
				{
					Logger.Debug("[SkinPackageManager] NormalizeFolder: no manifest found in '" + text + "', skipping.");
					continue;
				}
				SkinGroup skinGroup = JsonUtils.DeserializeFromFile<SkinGroup>(text2);
				if (skinGroup == null || string.IsNullOrEmpty(skinGroup.Guid))
				{
					Logger.Error("[SkinPackageManager] NormalizeFolder: could not read a valid GUID from '" + text2 + "'. Unstaging folder for installation.");
					try
					{
						Directory.Delete(text, recursive: true);
					}
					catch (Exception ex)
					{
						Logger.Error("[SkinPackageManager] NormalizeFolder: failed to delete & unstage folder '" + text + "': " + ex.Message);
					}
					continue;
				}
				string fileName = Path.GetFileName(text);
				if (string.Equals(fileName, skinGroup.Guid, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				string text3 = Path.Combine(folderPath, skinGroup.Guid);
				if (Directory.Exists(text3))
				{
					Logger.Error($"[SkinPackageManager] NormalizeFolder: cannot rename '{fileName}' -> '{skinGroup.Guid}' -- a folder with that name already exists. Unstaging folder for installation.");
					try
					{
						Directory.Delete(text, recursive: true);
					}
					catch (Exception ex2)
					{
						Logger.Error("[SkinPackageManager] NormalizeFolder: failed to delete & unstage folder '" + text + "': " + ex2.Message);
					}
					continue;
				}
				try
				{
					Directory.Move(text, text3);
					Logger.Info($"[SkinPackageManager] NormalizeFolder: renamed '{fileName}' -> '{skinGroup.Guid}'");
				}
				catch (Exception ex3)
				{
					Logger.Error($"[SkinPackageManager] NormalizeFolder: failed to rename '{fileName}' -> '{skinGroup.Guid}': {ex3.Message}");
				}
			}
		}
	}
	[RegisterIl2Cpp]
	public class SkinProcess : MonoBehaviour
	{
		private const float DumpDirtyCheckInterval = 30f;

		private const float SweepInterval = 1f;

		private const double TextureUploadBudgetMs = 4.0;

		private float _nextDumpDirtyCheckTime;

		private float _nextSweepTime;

		private void Update()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			TextureLoader.Pump(4.0);
			GearIcons.Pump(4.0);
			GearIconPatches.Tick();
			if (Time.time >= _nextSweepTime)
			{
				SkinManager.SweepIdle();
				_nextSweepTime = Time.time + 1f;
			}
			if (ConfigMgr.EnableHotReloadKey && Input.GetKeyDown(ConfigMgr.HotReloadKey))
			{
				((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(SkinManager.Reload()));
			}
			if (Time.time >= _nextDumpDirtyCheckTime)
			{
				GearDump.FlushNow();
				MeshDump.FlushNow();
				_nextDumpDirtyCheckTime = Time.time + 30f;
			}
		}
	}
}
namespace Skins.Utils
{
	public static class FileUtils
	{
		public static IEnumerable<string> FileInEachSubdirectory(string dir, string fileName)
		{
			if (!Directory.Exists(dir))
			{
				yield break;
			}
			foreach (string item in Directory.EnumerateDirectories(dir))
			{
				string text = Path.Combine(item, fileName);
				if (File.Exists(text))
				{
					yield return text;
				}
			}
		}

		public static IEnumerable<string> FilesWithExtensionRecursive(string dir, string extension)
		{
			if (!Directory.Exists(dir))
			{
				yield break;
			}
			string text = (extension.StartsWith(".") ? extension : ("." + extension));
			foreach (string item in Directory.EnumerateFiles(dir, "*" + text, SearchOption.AllDirectories))
			{
				yield return item;
			}
		}

		public static IEnumerable<string> FilesWithExtension(string dir, string extension)
		{
			if (!Directory.Exists(dir) || string.IsNullOrWhiteSpace(extension))
			{
				yield break;
			}
			string text = (extension.StartsWith(".") ? extension : ("." + extension));
			foreach (string item in Directory.EnumerateFiles(dir, "*" + text, SearchOption.TopDirectoryOnly))
			{
				yield return item;
			}
		}

		public static void MoveFile(string sourcePath, string destPath, bool overwrite = false)
		{
			if (!File.Exists(sourcePath))
			{
				Logger.Warn("[FileUtils] Source file does not exist: " + sourcePath);
				return;
			}
			if (File.Exists(destPath))
			{
				if (!overwrite)
				{
					Logger.Warn("[FileUtils] Destination file already exists: " + destPath);
					return;
				}
				File.Delete(destPath);
			}
			File.Copy(sourcePath, destPath);
			File.Delete(sourcePath);
		}

		public static void MoveDirectory(string sourceDir, string destDir, bool overwrite = false)
		{
			if (!Directory.Exists(sourceDir))
			{
				Logger.Warn("[FileUtils] Source directory does not exist: " + sourceDir);
				return;
			}
			if (Directory.Exists(destDir))
			{
				if (!overwrite)
				{
					Logger.Warn("[FileUtils] Destination directory already exists: " + destDir);
					return;
				}
				Directory.Delete(destDir, recursive: true);
			}
			Directory.CreateDirectory(destDir);
			foreach (string item in Directory.EnumerateFiles(sourceDir))
			{
				string destFileName = Path.Combine(destDir, Path.GetFileName(item));
				File.Copy(item, destFileName);
				File.Delete(item);
			}
			foreach (string item2 in Directory.EnumerateDirectories(sourceDir))
			{
				string destDir2 = Path.Combine(destDir, Path.GetFileName(item2));
				MoveDirectory(item2, destDir2, overwrite);
			}
			Directory.Delete(sourceDir);
		}
	}
	public static class GearUtils
	{
		private const string GearIdPattern = "^OfflineGear_ID_(\\d+)$";

		private static readonly Regex GearIdRe = new Regex("^OfflineGear_ID_(\\d+)$", RegexOptions.Compiled);

		public static uint? ExtractOfflineGearId(string? gearPartId)
		{
			if (gearPartId == null)
			{
				return null;
			}
			Match match = GearIdRe.Match(gearPartId);
			if (!match.Success)
			{
				return null;
			}
			if (uint.TryParse(match.Groups[1].Value, out var result))
			{
				return result;
			}
			return null;
		}

		public static bool TryGetOfflineGearId(BackpackItem item, out uint gearId)
		{
			if (item.GearIDRange != null)
			{
				return TryGetOfflineGearId(item.GearIDRange, out gearId);
			}
			gearId = 0u;
			return false;
		}

		public static bool TryGetOfflineGearId(ItemEquippable item, out uint gearId)
		{
			if (item.GearIDRange != null)
			{
				return TryGetOfflineGearId(item.GearIDRange, out gearId);
			}
			gearId = 0u;
			return false;
		}

		public static bool TryGetOfflineGearId(GearIDRange idRange, out uint gearId)
		{
			uint? num = ExtractOfflineGearId(idRange.PlayfabItemInstanceId);
			if (num.HasValue)
			{
				gearId = num.Value;
				return true;
			}
			gearId = 0u;
			return false;
		}

		public static bool TryGetShellType(GearIDRange? idRange, out ShellTypes type)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected I4, but got Unknown
			type = (ShellTypes)0;
			if (idRange == null)
			{
				return false;
			}
			uint compID = idRange.GetCompID((eGearComponent)7);
			if (!GameDataBlockBase<WeaponShellCasingDataBlock>.HasBlock(compID))
			{
				return false;
			}
			WeaponShellCasingDataBlock block = GameDataBlockBase<WeaponShellCasingDataBlock>.GetBlock(compID);
			type = (ShellTypes)(int)block.ShellCasingType;
			return true;
		}

		public static bool TryGetShellTypePrefab(ShellTypes type, [NotNullWhen(true)] out GameObject? prefab)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			WeaponShellManager current = WeaponShellManager.Current;
			prefab = (GameObject?)((type - 1) switch
			{
				0 => current.m_shell_9mm_prefab, 
				1 => current.m_shell_45_ACP_prefab, 
				2 => current.m_shell_338_prefab, 
				3 => current.m_shell_12_Gauge_prefab, 
				_ => null, 
			});
			return (Object)(object)prefab != (Object)null;
		}
	}
	public static class GuiUtils
	{
		public static void SetItemColor(CM_Item item, Color spriteColor, Color textColorAll)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			Color spriteColorOut = default(Color);
			((Color)(ref spriteColorOut))..ctor(spriteColor.r, spriteColor.g, spriteColor.b, item.m_spriteAlphaOut);
			Color spriteColorOver = default(Color);
			((Color)(ref spriteColorOver))..ctor(spriteColor.r, spriteColor.g, spriteColor.b, item.m_spriteAlphaOver);
			Color val = default(Color);
			((Color)(ref val))..ctor(textColorAll.r, textColorAll.g, textColorAll.b, item.m_textAlphaOut);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(textColorAll.r, textColorAll.g, textColorAll.b, item.m_textAlphaOver);
			item.m_spriteColorOrg = spriteColor;
			item.m_spriteColorOut = spriteColorOut;
			item.m_spriteColorOver = spriteColorOver;
			if (item.m_texts != null)
			{
				for (int i = 0; i < ((Il2CppArrayBase<TextMeshPro>)(object)item.m_texts).Count; i++)
				{
					((Il2CppArrayBase<Color>)(object)item.m_textColorOrg)[i] = textColorAll;
					((Il2CppArrayBase<Color>)(object)item.m_textColorOut)[i] = val;
					((Il2CppArrayBase<Color>)(object)item.m_textColorOver)[i] = val2;
				}
			}
			item.OnHoverOut();
		}

		public static void FixLobbyScrollItem(CM_LobbyScrollItem item, float? newX = null, float? newY = null, float leftLineThickness = 12f, float lineThickness = 4f)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = ((Il2CppObjectBase)((Component)item).transform).TryCast<RectTransform>();
			RectTransform component = ((Component)CustomExtensions.FindChildRecursive((Transform)(object)obj, "StretchLineT", true)).GetComponent<RectTransform>();
			RectTransform component2 = ((Component)CustomExtensions.FindChildRecursive((Transform)(object)obj, "StretchLineB", true)).GetComponent<RectTransform>();
			RectTransform component3 = ((Component)CustomExtensions.FindChildRecursive((Transform)(object)obj, "StretchLineL", true)).GetComponent<RectTransform>();
			RectTransform component4 = ((Component)CustomExtensions.FindChildRecursive((Transform)(object)obj, "StretchLineR", true)).GetComponent<RectTransform>();
			RectTransform component5 = ((Component)((Transform)component).parent).GetComponent<RectTransform>();
			RectTransform component6 = ((Component)CustomExtensions.FindChildRecursive((Transform)(object)component5, "Background", true)).GetComponent<RectTransform>();
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(newX ?? component5.sizeDelta.x, newY ?? component5.sizeDelta.y);
			component5.sizeDelta = val;
			component6.anchorMin = Vector2.zero;
			component6.anchorMax = Vector2.one;
			component6.offsetMin = Vector2.zero;
			component6.offsetMax = Vector2.zero;
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.offsetMin = new Vector2(0f, 0f - lineThickness);
			component.offsetMax = new Vector2(0f, 0f);
			component2.anchorMin = new Vector2(0f, 0f);
			component2.anchorMax = new Vector2(1f, 0f);
			component2.offsetMin = new Vector2(0f, 0f - lineThickness);
			component2.offsetMax = new Vector2(0f, 0f);
			component3.anchorMin = new Vector2(0f, 0f);
			component3.anchorMax = new Vector2(0f, 1f);
			component3.offsetMin = new Vector2(0f, 0f);
			component3.offsetMax = new Vector2(leftLineThickness, 0f);
			component4.anchorMin = new Vector2(1f, 0f);
			component4.anchorMax = new Vector2(1f, 1f);
			component4.offsetMin = new Vector2(0f, 0f);
			component4.offsetMax = new Vector2(lineThickness, 0f);
			foreach (UI_SpriteResizer componentsInChild in ((Component)item).GetComponentsInChildren<UI_SpriteResizer>())
			{
				if (Object.op_Implicit((Object)(object)componentsInChild))
				{
					componentsInChild.Resize();
				}
			}
			((CM_Item)item).m_collider.size = val;
		}
	}
	public static class JsonUtils
	{
		public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
		{
			ContractResolver = (IContractResolver)(object)new SkinsContractResolver()
		};

		public static T? Deserialize<T>(string json)
		{
			return JsonConvert.DeserializeObject<T>(json, Settings);
		}

		public static T? DeserializeFromFile<T>(string path)
		{
			if (!File.Exists(path))
			{
				Logger.Warn("[JsonUtils] File not found: '" + path + "'");
				return default(T);
			}
			return Deserialize<T>(File.ReadAllText(path));
		}
	}
	public class SkinsContractResolver : DefaultContractResolver
	{
		protected override JsonConverter? ResolveContractConverter(Type objectType)
		{
			if (objectType == typeof(IMaterialProperty))
			{
				return (JsonConverter?)(object)new MaterialPropertyConverter();
			}
			return ((DefaultContractResolver)this).ResolveContractConverter(objectType);
		}
	}
	[RegisterIl2Cpp]
	public class LifecycleHook : MonoBehaviour
	{
		public event Action? OnStarted;

		public event Action? OnEnabled;

		public event Action? OnDisabled;

		public event Action? OnDestroyed;

		private void Start()
		{
			this.OnStarted?.Invoke();
		}

		private void OnEnable()
		{
			this.OnEnabled?.Invoke();
		}

		private void OnDisable()
		{
			this.OnDisabled?.Invoke();
		}

		private void OnDestroy()
		{
			this.OnDestroyed?.Invoke();
		}
	}
	public class LocaleUtils
	{
		public static readonly Dictionary<string, string> LocaleKeyToDisplayName = new Dictionary<string, string>
		{
			{ "en", "English" },
			{ "fr", "Français" },
			{ "de", "Deutsch" },
			{ "es", "Español" },
			{ "it", "Italiano" },
			{ "ja", "日本語" },
			{ "ko", "한국어" },
			{ "pt-BR", "Português (Brasil)" },
			{ "ru", "Русский" },
			{ "pl", "Polski" },
			{ "zh-Hans", "简体中文" },
			{ "zh-Hant", "繁體中文" }
		};

		public static string LocaleKeyFromEnum(Language key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected I4, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			return (key - 1) switch
			{
				0 => "en", 
				1 => "fr", 
				3 => "de", 
				4 => "es", 
				2 => "it", 
				8 => "ja", 
				9 => "ko", 
				6 => "pt-BR", 
				5 => "ru", 
				7 => "pl", 
				11 => "zh-Hans", 
				10 => "zh-Hant", 
				_ => throw new ArgumentOutOfRangeException("key", key, null), 
			};
		}

		public static void SetTranslation(TextDataBlock db, string locale, string text)
		{
			switch (locale)
			{
			case "en":
				db.English = text;
				break;
			case "fr":
				db.French = LanguageData.op_Implicit(text);
				break;
			case "de":
				db.German = LanguageData.op_Implicit(text);
				break;
			case "es":
				db.Spanish = LanguageData.op_Implicit(text);
				break;
			case "it":
				db.Italian = LanguageData.op_Implicit(text);
				break;
			case "ja":
				db.Japanese = LanguageData.op_Implicit(text);
				break;
			case "ko":
				db.Korean = LanguageData.op_Implicit(text);
				break;
			case "pt-BR":
				db.Portuguese_Brazil = LanguageData.op_Implicit(text);
				break;
			case "ru":
				db.Russian = LanguageData.op_Implicit(text);
				break;
			case "pl":
				db.Polish = LanguageData.op_Implicit(text);
				break;
			case "zh-Hans":
				db.Chinese_Simplified = LanguageData.op_Implicit(text);
				break;
			case "zh-Hant":
				db.Chinese_Traditional = LanguageData.op_Implicit(text);
				break;
			}
		}

		public static uint GetSlotGearSelectTextDbId(InventorySlot slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected I4, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			switch (slot - 1)
			{
			default:
				if ((int)slot == 10)
				{
					return 490u;
				}
				return 0u;
			case 0:
				return 487u;
			case 1:
				return 488u;
			case 2:
				return 489u;
			}
		}

		public static string GetSlotGearSelectLocalizedText(InventorySlot slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Text.Get(GetSlotGearSelectTextDbId(slot));
		}
	}
	public static class LogDumper
	{
		private static readonly Dictionary<string, StreamWriter> LogStreams = new Dictionary<string, StreamWriter>();

		private static readonly Dictionary<string, HashSet<int>> LoggedIds = new Dictionary<string, HashSet<int>>();

		public static void Dump(string name, string content, bool append = false)
		{
			if (!LogStreams.TryGetValue(name, out StreamWriter value))
			{
				value = new StreamWriter(Path.Combine(ModData.DumpFolder, name + ".log"), append);
				LogStreams[name] = value;
				LoggedIds[name] = new HashSet<int>();
			}
			value.WriteLine(content);
			value.Flush();
		}

		public static void DumpUnique(string name, int id, string content, bool append = false)
		{
			if (!LogStreams.TryGetValue(name, out StreamWriter value))
			{
				value = new StreamWriter(Path.Combine(ModData.DumpFolder, name + ".log"), append);
				LogStreams[name] = value;
				LoggedIds[name] = new HashSet<int>();
			}
			if (!LoggedIds[name].Contains(id))
			{
				value.WriteLine(content);
				value.Flush();
				LoggedIds[name].Add(id);
			}
		}
	}
	public static class NameUtils
	{
		private static readonly Regex CleanPattern = new Regex("\\s*(?:\\(Clone\\)|\\(Instance\\)|Instance).*$", RegexOptions.Compiled);

		public static string GetCleanName(string name)
		{
			return CleanPattern.Replace(name, "");
		}
	}
	public static class PluginUtils
	{
		public static bool IsPluginLoaded(string pluginGuid)
		{
			return ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(pluginGuid);
		}
	}
	public static class TextureUtils
	{
		public static Texture2D CreateBlankWhiteTexture()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, Color.white);
			val.Apply();
			return val;
		}

		public static Texture2D CreateBlankTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		public static Sprite SpriteFromRenderTexture(RenderTexture rt)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(((Texture)rt).width, ((Texture)rt).height, (TextureFormat)4, false);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = rt;
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)rt).width, (float)((Texture)rt).height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		public static Sprite SpriteFromTexture2D(Texture2D tex)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			float num = ((Texture)tex).width;
			float num2 = ((Texture)tex).height;
			return Sprite.Create(tex, new Rect(0f, 0f, num, num2), new Vector2(0.5f, 0.5f));
		}

		public static TextureOptions InferOptionsFromSlot(string slot)
		{
			return new TextureOptions(slot switch
			{
				"_BumpMap" => true, 
				"_MetallicGlossMap" => true, 
				"_AOCurveTex" => true, 
				"_SpecGlossMap" => true, 
				"_HeightMap" => true, 
				"_DistortionTex" => true, 
				"_DistortionSignal" => true, 
				_ => false, 
			}, PersistentConfig<UserConfig>.Instance?.PluginConfig.EnableMipMaps ?? false);
		}
	}
	public class TMPUtils
	{
		public static bool CreateTMP(string name, Transform? parent, [NotNullWhen(true)] out TextMeshPro? tp)
		{
			//IL_0058: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer;
			object obj;
			if (watermarkLayer == null)
			{
				obj = null;
			}
			else
			{
				PUI_Watermark watermark = watermarkLayer.m_watermark;
				obj = ((watermark != null) ? watermark.m_fpsText : null);
			}
			TextMeshPro val = (TextMeshPro)obj;
			if ((Object)(object)parent == (Object)null || (Object)(object)val == (Object)null)
			{
				tp = null;
				return false;
			}
			tp = Object.Instantiate<TextMeshPro>(val, parent, false);
			((Object)tp).name = name;
			((TMP_Text)tp).rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.pivot = new Vector2(1f, 0f);
			((TMP_Text)tp).rectTransform.anchoredPosition3D = new Vector3(0f, 2f, 0f);
			((Transform)((TMP_Text)tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 0f);
			((TMP_Text)tp).enableAutoSizing = false;
			((TMP_Text)tp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)tp).alignment = (TextAlignmentOptions)513;
			((TMP_Text)tp).fontSize = 16f;
			return true;
		}

		public static bool CreateTMPUGUI(string name, Transform? parent, [NotNullWhen(true)] out TextMeshProUGUI? tp)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0052: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer;
			object obj;
			if (watermarkLayer == null)
			{
				obj = null;
			}
			else
			{
				PUI_Watermark watermark = watermarkLayer.m_watermark;
				obj = ((watermark != null) ? watermark.m_fpsText : null);
			}
			TextMeshPro val = (TextMeshPro)obj;
			GameObject val2 = new GameObject();
			val2.transform.SetParent(parent, false);
			tp = val2.AddComponent<TextMeshProUGUI>();
			((Object)tp).name = name;
			((TMP_Text)tp).rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.pivot = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.anchoredPosition3D = new Vector3(0f, 0f, 0f);
			((Transform)((TMP_Text)tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 0f);
			((TMP_Text)tp).enableAutoSizing = false;
			((TMP_Text)tp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)tp).alignment = (TextAlignmentOptions)514;
			((TMP_Text)tp).fontSize = 16f;
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)tp).font = ((TMP_Text)val).font;
				((TMP_Text)tp).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial;
			}
			return true;
		}
	}
}
namespace Skins.Utils.Ext
{
	public static class BackpackExtensions
	{
		public static TargetContext GetContextForSlot(this PlayerBackpack bkpk, InventorySlot slot)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			TargetContext targetContext = new TargetContext();
			BackpackItem item = default(BackpackItem);
			if ((slot - 1 <= 2 || (int)slot == 10) && bkpk.TryGetBackpackItem(slot, ref item) && GearUtils.TryGetOfflineGearId(item, out var gearId))
			{
				targetContext.OfflineGearId = gearId;
			}
			return targetContext;
		}
	}
	public static class ComponentExtensions
	{
		public static T? AddComponentIfMissing<T>(this GameObject obj) where T : Component
		{
			if (!((Object)(object)obj.GetComponent<T>() == (Object)null))
			{
				return default(T);
			}
			return obj.AddComponent<T>();
		}

		public static T GetOrAddComponent<T>(this GameObject obj) where T : Component
		{
			T val = obj.GetComponent<T>();
			if ((Object)(object)val == (Object)null)
			{
				val = obj.AddComponent<T>();
			}
			return val;
		}

		public static T? GetComponentSafe<T>(this GameObject? obj) where T : Component
		{
			if ((Object)(object)obj == (Object)null)
			{
				return default(T);
			}
			return obj.GetComponent<T>();
		}

		public static T? GetComponentSafe<T>(this Component? obj) where T : Component
		{
			if ((Object)(object)obj == (Object)null)
			{
				return default(T);
			}
			return obj.GetComponent<T>();
		}
	}
	public static class EnumeratorExtensions
	{
		public static void RunSync(this IEnumerator enumerator)
		{
			Stack<IEnumerator> stack = new Stack<IEnumerator>();
			stack.Push(enumerator);
			while (stack.Count > 0)
			{
				IEnumerator enumerator2 = stack.Peek();
				if (enumerator2.MoveNext())
				{
					if (enumerator2.Current is IEnumerator item)
					{
						stack.Push(item);
					}
				}
				else
				{
					stack.Pop();
				}
			}
		}
	}
}
namespace Skins.UI
{
	[RegisterIl2Cpp]
	public class DevUI : MonoBehaviour
	{
		private static readonly Vector2 ReferenceResolution = new Vector2(2560f, 1440f);

		private Canvas _canvas;

		private CanvasScaler _canvasScaler;

		private GameObject _centerContainer;

		private Image _centerContainerImage;

		private TMP_Text _centerDisplayTxt;

		private Image _progressBarFill;

		private RectTransform _progressBarFillRt;

		public static DevUI? Instance { get; private set; } = null;

		private void Awake()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				Logger.Warn("[DevUI] Instance already exists, destroying new instance.");
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			((Object)((Component)this).gameObject).name = "io.takina.gtfo.Skins.DevUI";
			_canvas = ((Component)this).gameObject.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 1000;
			_canvasScaler = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			_canvasScaler.uiScaleMode = (ScaleMode)1;
			_canvasScaler.referenceResolution = ReferenceResolution;
			_canvasScaler.m_MatchWidthOrHeight = 1f;
			CreateElements();
		}

		public void SetCenterDisplayActive(bool active)
		{
			if (!((Object)(object)_centerContainer == (Object)null))
			{
				_centerContainer.SetActive(active);
			}
		}

		public void SetCenterDisplayText(string text)
		{
			if (!((Object)(object)_centerDisplayTxt == (Object)null))
			{
				_centerDisplayTxt.text = text;
			}
		}

		public void SetCenterDisplayProgress(float progress)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_progressBarFill == (Object)null))
			{
				RectTransform progressBarFillRt = _progressBarFillRt;
				progressBarFillRt.anchorMin = Vector2.zero;
				progressBarFillRt.anchorMax = new Vector2(Mathf.Clamp01(progress), 1f);
				progressBarFillRt.offsetMin = Vector2.zero;
				progressBarFillRt.offsetMax = Vector2.zero;
			}
		}

		private void CreateElements()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			_centerContainer = new GameObject("CenterTextDisplay Container");
			_centerContainer.transform.SetParent(((Component)this).gameObject.transform, false);
			RectTransform obj = _centerContainer.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 0.33f);
			obj.anchorMax = new Vector2(1f, 0.66f);
			obj.anchoredPosition = Vector2.zero;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			_centerContainerImage = _centerContainer.AddComponent<Image>();
			((Graphic)_centerContainerImage).color = new Color(0f, 0f, 0f, 0.95f);
			if (TMPUtils.CreateTMPUGUI("io.takina.gtfo.Skins.CenterTextDisplay", _centerContainer.transform, out TextMeshProUGUI tp))
			{
				((TMP_Text)tp).enableAutoSizing = true;
				((TMP_Text)tp).m_maxFontSize = 100f;
				((TMP_Text)tp).m_minFontSize = 32f;
				((Graphic)tp).color = UIManager.AccentColor;
				((TMP_Text)tp).rectTransform.sizeDelta = new Vector2(ReferenceResolution.x, ReferenceResolution.y / 3f);
				_centerDisplayTxt = (TMP_Text)(object)tp;
			}
			GameObject val = new GameObject("ProgressBar Background");
			val.transform.SetParent(_centerContainer.transform, false);
			RectTransform obj2 = val.AddComponent<RectTransform>();
			obj2.anchorMin = new Vector2(0f, 0f);
			obj2.anchorMax = new Vector2(1f, 0f);
			obj2.pivot = new Vector2(0.5f, 0f);
			obj2.anchoredPosition = Vector2.zero;
			obj2.sizeDelta = new Vector2(0f, 8f);
			((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.15f);
			GameObject val2 = new GameObject("ProgressBar Fill");
			val2.transform.SetParent(val.transform, false);
			_progressBarFillRt = val2.AddComponent<RectTransform>();
			_progressBarFillRt.anchorMin = Vector2.zero;
			_progressBarFillRt.anchorMax = Vector2.one;
			_progressBarFillRt.offsetMin = Vector2.zero;
			_progressBarFillRt.offsetMax = Vector2.zero;
			_progressBarFill = val2.AddComponent<Image>();
			((Graphic)_progressBarFill).color = UIManager.AccentColor;
			_progressBarFill.type = (Type)3;
			_progressBarFill.fillMethod = (FillMethod)0;
			_progressBarFill.fillAmount = 0f;
			_centerContainer.SetActive(false);
		}
	}
	[HarmonyPatch]
	public class UIManager
	{
		public static readonly Color AccentColor = Color32.op_Implicit(new Color32((byte)137, (byte)180, (byte)250, byte.MaxValue));

		private static readonly Action<int> OnOfflineGearShowSkinSelectPopup = OpenOfflineGearSkinSelect;

		public static readonly List<InventorySlot> GearSlots = new List<InventorySlot>
		{
			(InventorySlot)1,
			(InventorySlot)2,
			(InventorySlot)3,
			(InventorySlot)10
		};

		private static Sprite? _pluginIcon = null;

		public static void Initialize()
		{
			Text.UpdateAllTexts();
			Texture2D val = TextureLibrary.Load(Path.Combine(ModData.PluginFolder, "icon.png"), default(TextureOptions), managed: false);
			if ((Object)(object)val != (Object)null)
			{
				_pluginIcon = TextureUtils.SpriteFromTexture2D(val);
			}
		}

		private static void OpenOfflineGearSkinSelect(int _)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
			SelectionPopupMenu selectionPopupMenu = new SelectionPopupMenu();
			BackpackItem val = default(BackpackItem);
			foreach (InventorySlot gearSlot in GearSlots)
			{
				Logger.Debug($"[UIManager.OpenOfflineGearSkinSelect] Setting up skin select for slot {gearSlot}");
				SelectionPopupHeader header = new SelectionPopupHeader(LocaleUtils.GetSlotGearSelectLocalizedText(gearSlot))
				{
					SetActiveConfirmText = "<color=orange>" + Loc.T("gear.select.clickAgain") + "</color>",
					IsActiveText = "<color=green>" + Loc.T("gear.select.active") + "</color>"
				};
				TargetContext ctx = localBackpack.GetContextForSlot(gearSlot);
				BackpackItem bkpkItem = (localBackpack.TryGetBackpackItem(gearSlot, ref val) ? val : null);
				SelectionPopupHeader selectionPopupHeader = header;
				UserConfig? instance = PersistentConfig<UserConfig>.Instance;
				selectionPopupHeader.ActiveItemID = ((instance != null && instance.CurrentSkinConfig.OfflineGear.TryGetValue(ctx.OfflineGearId.GetValueOrDefault(), out string value)) ? value : "10chambers.vanilla");
				AddGroup(SkinGroup.Vanilla);
				foreach (SkinGroup allMatchingGroup in SkinManager.GetAllMatchingGroups(ctx))
				{
					AddGroup(allMatchingGroup);
				}
				if (header.Items.Any((ISelectionPopupItem it) => it.ID == header.ActiveItemID))
				{
					header.LastSelectedItemID = header.ActiveItemID;
				}
				selectionPopupMenu.AddHeader(header);
				void AddGroup(SkinGroup group)
				{
					SkinSelectionPopupItem obj = new SkinSelectionPopupItem
					{
						DisplayName = group.Name.Resolve(),
						ID = group.Guid,
						SubTitle = group.Author.Resolve(),
						Description = group.Description?.Resolve(),
						setActiveAction = OnOfflineGearSkinSelected,
						upperTextCustomization = AuthorTextDecoration,
						subtitleTextCustomization = DescriptionTextDecoration,
						Context = ctx
					};
					BackpackItem obj2 = bkpkItem;
					object obj3;
					if (obj2 == null)
					{
						obj3 = null;
					}
					else
					{
						Item instance2 = obj2.Instance;
						obj3 = ((instance2 != null) ? ((Component)instance2).gameObject : null);
					}
					if (obj3 == null)
					{
						obj3 = null;
					}
					obj.ApplicationTarget = (GameObject?)obj3;
					BackpackItem obj4 = bkpkItem;
					obj.GearID = ((obj4 != null) ? obj4.GearIDRange : null);
					obj.SkinGUID = group.Guid;
					obj.IsVanilla = group.Guid == SkinGroup.Vanilla.Guid;
					SkinSelectionPopupItem item = obj;
					if ((Object)(object)_pluginIcon != (Object)null)
					{
						item.SpriteLarge = _pluginIcon;
						item.SpriteSmall = _pluginIcon;
					}
					if (GearIcons.Enabled)
					{
						BackpackItem obj5 = bkpkItem;
						if (((obj5 != null) ? obj5.GearIDRange : null) != null)
						{
							GearIcons.Request(bkpkItem.GearIDRange, group, delegate(Sprite sprite)
							{
								item.SetSprites(sprite, sprite);
							});
						}
					}
					header.AddItem(item);
				}
			}
			selectionPopupMenu.Show();
		}

		private static void OnOfflineGearSkinSelected(ISelectionPopupItem item)
		{
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if (!(item is SkinSelectionPopupItem skinSelectionPopupItem))
			{
				Logger.Warn("[UIManager] OnSkinSelected called with non-skin item.");
				return;
			}
			TargetContext context = skinSelectionPopupItem.Context;
			if (!context.OfflineGearId.HasValue)
			{
				Logger.Warn("[UIManager] Selected skin for item with no offline gear id - context: " + context);
				return;
			}
			string text = (skinSelectionPopupItem.IsVanilla ? "10chambers.vanilla" : skinSelectionPopupItem.SkinGUID);
			if (PersistentConfig<UserConfig>.Instance != null)
			{
				if (PersistentConfig<UserConfig>.Instance.CurrentSkinConfig.OfflineGear.TryGetValue(context.OfflineGearId.Value, out string value) && value == text)
				{
					return;
				}
				PersistentConfig<UserConfig>.Instance.CurrentSkinConfig.OfflineGear[context.OfflineGearId.Value] = text;
				PersistentConfig<UserConfig>.Save();
			}
			else
			{
				Logger.Warn("[UIManager] Cannot save skin selection because UserConfig.Instance is null.");
			}
			if ((Object)(object)skinSelectionPopupItem.ApplicationTarget != (Object)null)
			{
				ItemEquippable component = skinSelectionPopupItem.ApplicationTarget.GetComponent<ItemEquippable>();
				if ((Object)(object)component != (Object)null)
				{
					WeaponShellCasingDataBlock shellCasingData = component.ShellCasingData;
					ShellTypes? val = ((shellCasingData != null) ? new ShellTypes?(shellCasingData.ShellCasingType) : ((ShellTypes?)null));
					if (val.HasValue)
					{
						ShellSkinning.SetupPoolForGear(context.OfflineGearId.Value, val.Value);
					}
				}
				SkinManager.UpdateTargetsUnder(skinSelectionPopupItem.ApplicationTarget);
			}
			GearIconPatches.RegenerateIcons(skinSelectionPopupItem.GearID);
		}

		private static string AuthorTextDecoration(ISelectionPopupItem item, string text)
		{
			return text;
		}

		private static string DescriptionTextDecoration(ISelectionPopupItem item, string text)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return "<" + ColorExt.ToHtml(AccentColor) + ">" + text + "</color>";
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "SetupFromPage")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPriority(700)]
		private static void AddLobbyBarSelectSkinEntryPoint(CM_PlayerLobbyBar __instance)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = ((Component)__instance.m_weaponsHeaderText.transform).GetComponent<RectTransform>();
			CM_LobbyScrollItem val = Object.Instantiate<CM_LobbyScrollItem>(__instance.m_clothesButton, ((Component)__instance.m_clothesButton).transform.parent, true);
			((RectTransformComp)val).Setup();
			((Object)((Component)val).gameObject).name = "Skins Select Button";
			((CM_Item)val).SetOnBtnPressCallback(Action<int>.op_Implicit(OnOfflineGearShowSkinSelectPopup));
			RectTransform val2 = ((Il2CppObjectBase)((Component)val).transform).TryCast<RectTransform>();
			if ((Object)(object)val2 != (Object)null && (Object)(object)component != (Object)null)
			{
				Vector2 anchoredPosition = val2.anchoredPosition;
				anchoredPosition.y = component.anchoredPosition.y + 15f;
				val2.anchoredPosition = anchoredPosition;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(1f, 0.5f);
				val2.anchorMax = val3;
				val2.anchorMin = val3;
				((Transform)val2).Translate(new Vector3(32f, 0f, 0f));
				if (PluginUtils.IsPluginLoaded("dev.aurirex.gtfo.legacylobby"))
				{
					((Transform)val2).Translate(new Vector3(83f, 160f, 0f));
				}
				GuiUtils.FixLobbyScrollItem(val, val2.sizeDelta.x * 0.4f);
				GuiUtils.SetItemColor((CM_Item)(object)val, AccentColor, Color.white);
			}
			Loc.TrySetExistingTMP((Component)(object)val, "ui.skinsButton");
			GameStateCache.LobbyBar2LobbyScrollItem.Save((Component)(object)__instance, val);
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "PrepareForIntro")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Postfix__LobbyBar_PrepareForIntro(CM_PlayerLobbyBar __instance)
		{
			CM_LobbyScrollItem val = GameStateCache.LobbyBar2LobbyScrollItem.Get((Component)(object)__instance);
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "SpawnPlayerModel")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Postfix__LobbyBar_SpawnPlayerModel(CM_PlayerLobbyBar __instance)
		{
			CM_LobbyScrollItem val = GameStateCache.LobbyBar2LobbyScrollItem.Get((Component)(object)__instance);
			if ((Object)(object)val != (Object)null && (Object)(object)__instance.m_player != (Object)null && __instance.m_player.IsLocal)
			{
				CoroutineManager.BlinkIn((CM_Item)(object)val, 1.2f, (Transform)null);
			}
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "ShowWeaponSelectionPopup")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void AddWeaponSelectSkinEntryPoint(CM_PlayerLobbyBar __instance)
		{
		}

		[HarmonyPatch(typeof(CM_PageSettings), "Setup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPriority(700)]
		private static void AddHotReloadButton(CM_PageSettings __instance)
		{
			Logger.Warn("Uhh... maybe TheArchive should find a better way to store offset, because I hate to have to take VeryHigh priority ;)");
		}

		private static void OnPageMenuSettingReloadSkins(int _)
		{
			ReloadSkins();
		}

		public static void ReloadSkins()
		{
			if ((Object)(object)Plugin.UnityBehaviourProcess == (Object)null)
			{
				Logger.Error("[UIManager] Cannot reload skins because UnityBehaviourProcess is null.");
			}
			else
			{
				((MonoBehaviour)Plugin.UnityBehaviourProcess).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(SkinManager.Reload()));
			}
		}

		private static void OnPageMenuSettingOpenGlobalSkinsFolder(int _)
		{
			OpenGlobalSkinsFolder();
		}

		public static void OpenGlobalSkinsFolder()
		{
			Process.Start(new ProcessStartInfo
			{
				FileName = "explorer.exe",
				Arguments = ModData.SkinsFolder,
				UseShellExecute = true
			});
		}
	}
	public sealed class BoolHandle
	{
		private readonly Action<bool> _refresh;

		internal BoolHandle(Action<bool> refresh)
		{
			_refresh = refresh;
		}

		public void Refresh(bool value)
		{
			_refresh(value);
		}
	}
	public sealed class TextHandle
	{
		private readonly TextMeshPro _tmp;

		public TMP_Text TMP => (TMP_Text)(object)_tmp;

		internal TextHandle(TextMeshPro tmp)
		{
			_tmp = tmp;
		}

		public void SetVisible(bool visible)
		{
			if ((Object)(object)_tmp != (Object)null)
			{
				((Component)_tmp).gameObject.SetActive(visible);
			}
		}

		public void SetText(string text)
		{
			TextMeshPro tmp = _tmp;
			if (tmp != null)
			{
				((TMP_Text)tmp).SetText(text, true);
			}
		}
	}
	public sealed class EnumHandle<T>
	{
		private readonly Action<T> _refresh;

		internal EnumHandle(Action<T> refresh)
		{
			_refresh = refresh;
		}

		public void Refresh(T value)
		{
			_refresh(value);
		}
	}
	[HarmonyPatch]
	public class UISettings
	{
		private static class Layout
		{
			internal const float WindowX = 420f;

			internal const float WindowY = -200f;

			internal const float WindowWidth = 1020f;

			internal const float WindowHeight = 900f;

			internal const float ItemPadding = 5f;

			internal const float ControlW = 550f;

			internal const float ControlH = 50f;

			internal const float ControlOfsX = 250f;

			internal const float ControlOfsY = -25f;

			internal static readonly Vector3 WidgetAnchorPosition = new Vector3(-325f, 0f, 0f);
		}

		private static CM_PageSettings? _pageInstance;

		private static CM_ScrollWindow? _settingsWindow;

		private static CM_ScrollWindow? _popupWindow;

		private static GameObject? _settingsItemPrefab;

		private static Coroutine? _hideMessageCoroutine;

		public static TextHandle? ThMessageBox { get; private set; }

		public static LifecycleHook? SettingsWindowLifecycle { get; private set; }

		[HarmonyPatch(typeof(CM_PageSettings), "Setup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPriority(800)]
		private static void SetupSettingsPage(CM_PageSettings __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			_pageInstance = __instance;
			_settingsItemPrefab = __instance.m_settingsItemPrefab;
			_popupWindow = __instance.m_popupWindow;
			CM_Item val = __instance.CreateSingleButton(__instance.m_subMenuButtonPrefab, Loc.ID("settings.page.skins"));
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GuiUtils.SetItemColor(val, UIManager.AccentColor, UIManager.AccentColor);
			CM_ScrollWindow val2 = ((Il2CppObjectBase)((GuiLayer)((CM_PageBase)__instance).m_guiLayer).AddRectComp(__instance.m_scrollwindowPrefab, (GuiAnchor)1, new Vector2(420f, -200f), (Transform)(object)((CM_PageBase)__instance).m_movingContentHolder)).TryCast<CM_ScrollWindow>();
			if (!((Object)(object)val2 == (Object)null))
			{
				val2.Setup(((Component)__instance).transform);
				((RectTransformComp)val2).SetSize(new Vector2(1020f, 900f));
				((RectTransformComp)val2).SetVisible(false);
				if (((Il2CppArrayBase<CM_ScrollWindowHeader>)(object)val2.m_headers).Count > 0)
				{
					Loc.AttachToTMP((Component)(object)((Il2CppArrayBase<CM_ScrollWindowHeader>)(object)val2.m_headers)[0], "settings.page.skins");
				}
				((Component)val2).gameObject.AddComponent<LifecycleHook>();
				__instance.m_allSettingsWindows.Add(val2);
				_settingsWindow = val2;
				PopulateSettings(__instance, val2);
				val.OnBtnPressCallback += Action<int>.op_Implicit((Action<int>)OnSkinsSettingsButtonPressed);
			}
		}

		private static void PopulateSettings(CM_PageSettings instance, CM_ScrollWindow window)
		{
			List<iScrollWindowContent> val = new List<iScrollWindowContent>();
			AddHeader(instance, window, val, "settings.page.general.header");
			AddBoolToggle(instance, window, val, "settings.mipmaps", "settings.mipmaps.desc", () => PersistentConfig<UserConfig>.Instance?.PluginConfig.EnableMipMaps ?? true, delegate(bool enableMipMaps)
			{
				if (PersistentConfig<UserConfig>.Instance != null)
				{
					OnSettingsMipMapChanged();
					PersistentConfig<UserConfig>.Instance.PluginConfig.EnableMipMaps = enableMipMaps;
					PersistentConfig<UserConfig>.Save();
				}
			});
			AddHeader(instance, window, val, "settings.page.manage.header");
			AddButton(instance, window, val, "settings.page.manage.reload.label", "settings.page.manage.reload.desc", "settings.page.manage.reload.button", OnSettingsSkinReload);
			AddButton(instance, window, val, "settings.page.manage.globalSkinsFolder.label", "settings.page.manage.globalSkinsFolder.desc", "settings.page.manage.globalSkinsFolder.button", OnSettingsOpenSkinsFolder);
			AddButton(instance, window, val, "settings.page.manage.updateAllMatTargets.label", "settings.page.manage.updateAllMatTargets.desc", "settings.page.manage.updateAllMatTargets.button", OnSettingsUpdateAllGroupTargets);
			AddButton(instance, window, val, "settings.page.manage.reloadSkinsSettings.label", "settings.page.manage.reloadSkinsSettings.desc", "settings.page.manage.reloadSkinsSettings.button", OnSettingsReloadSkinsSettings);
			AddHeader(instance, window, val, "settings.page.info.header");
			AddTextDisplay(instance, window, val, "settings.page.info.version.label", "v0.12.0");
			ThMessageBox = AddTextRegion(instance, window, val, "settings.page.info.credits.label");
			window.SetContentItems(val, 5f);
			if ((Object)(object)SettingsWindowLifecycle != (Object)null)
			{
				SettingsWindowLifecycle.OnEnabled += OnSettingsPageEnabled;
				SettingsWindowLifecycle.OnDisabled += OnSettingsPageDisabled;
			}
		}

		private static void OnSettingsMipMapChanged()
		{
			if (ThMessageBox != null)
			{
				ShowInfoMessage("settings.page.info.reloadToTakeEffect");
			}
		}

		private static void OnSettingsOpenSkinsFolder()
		{
			if (ThMessageBox != null)
			{
				ShowInfoMessage("settings.page.info.reloadToTakeEffect");
				UIManager.OpenGlobalSkinsFolder();
			}
		}

		private static void OnSettingsSkinReload()
		{
			if (ThMessageBox != null)
			{
				HideInfoMessage();
				UIManager.ReloadSkins();
			}
		}

		private static void OnSettingsUpdateAllGroupTargets()
		{
			SkinManager.UpdateAllGroups();
			ShowInfoMessage("settings.page.info.allTargetsUpdated", 5f);
		}

		private static void OnSettingsReloadSkinsSettings()
		{
			PersistentConfig<UserConfig>.Load();
			SkinManager.UpdateAllGroups();
			ShowInfoMessage("settings.page.info.skinsSettingsReloaded", 5f);
		}

		private static void OnSettingsPageEnabled()
		{
		}

		private static void OnSettingsPageDisabled()
		{
			HideInfoMessage();
		}

		private static void ShowInfoMessage(string textKey)
		{
			if (ThMessageBox != null)
			{
				ThMessageBox.SetVisible(visible: true);
				ThMessageBox.SetText(Loc.T(textKey));
				ThMessageBox.TMP.alignment = (TextAlignmentOptions)514;
				if (_hideMessageCoroutine != null)
				{
					CoroutineManager.StopCoroutine(_hideMessageCoroutine);
					_hideMessageCoroutine = null;
				}
			}
		}

		private static void ShowInfoMessage(string textKey, float autoHideTimeout)
		{
			if (ThMessageBox != null)
			{
				ShowInfoMessage(textKey);
				_hideMessageCoroutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(AutoHideInfoMessage(autoHideTimeout)), (Action)null);
			}
		}

		private static IEnumerator AutoHideInfoMessage(float timeout)
		{
			yield return (object)new WaitForSeconds(timeout);
			HideInfoMessage();
			_hideMessageCoroutine = null;
		}

		private static void HideInfoMessage()
		{
			if (ThMessageBox != null)
			{
				ThMessageBox.SetText("");
				ThMessageBox.SetVisible(visible: false);
			}
		}

		private static CM_SettingsItem? CreateSettingsItem(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, Color? titleColor = null)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_settingsItemPrefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(_settingsItemPrefab, ((Component)window).transform);
			CM_SettingsItem component = val.GetComponent<CM_SettingsItem>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			((CM_Item)component).TextMeshRoot = ((Component)instance).transform;
			Transform obj = val.transform.Find("Title/TitleText");
			TextMeshPro val2 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshPro>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				if (titleColor.HasValue)
				{
					((Graphic)val2).color = titleColor.Value;
				}
				Loc.AttachToTMP((Component)(object)val2, labelKey);
			}
			else
			{
				((CM_Item)component).SetText(Loc.T(labelKey));
			}
			((RectTransformComp)component).ForcePopupLayer(true, (GameObject)null);
			iScrollWindowContent val3 = ((Il2CppObjectBase)component).TryCast<iScrollWindowContent>();
			if (val3 != null)
			{
				items.Add(val3);
			}
			else
			{
				Logger.Warn("[UISettings] CM_SettingsItem → iScrollWindowContent cast failed for '" + labelKey + "'");
			}
			return component;
		}

		private static (CM_Item button, TextMeshPro? label) SetupControlButton(CM_SettingsItem item, GameObject widgetPrefab)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(widgetPrefab, item.m_inputAlign, false);
			CM_Item val = obj.AddComponent<CM_Item>();
			((RectTransformComp)val).RectTrans.anchoredPosition3D = Layout.WidgetAnchorPosition;
			BoxCollider2D component = obj.GetComponent<BoxCollider2D>();
			if ((Object)(object)component != (Object)null)
			{
				component.size = new Vector2(550f, 50f);
				((Collider2D)component).offset = new Vector2(250f, -25f);
			}
			TextMeshPro componentInChildren = obj.GetComponentInChildren<TextMeshPro>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).fontStyle = (FontStyles)(((TMP_Text)componentInChildren).fontStyle | 0x10);
				((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4097;
			}
			return (button: val, label: componentInChildren);
		}

		private static CM_Item? SetupEnumButton(CM_SettingsItem item, out GameObject popupItemPrefab, out Transform? popupAnchor)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(item.m_enumDropdownInputPrefab, item.m_inputAlign);
			CM_SettingsEnumDropdownButton component = obj.GetComponent<CM_SettingsEnumDropdownButton>();
			CM_Item val = obj.AddComponent<CM_Item>();
			((RectTransformComp)val).Setup();
			popupItemPrefab = component.m_popupItemPrefab;
			popupAnchor = component.m_popupWindowAlign;
			BoxCollider2D component2 = obj.GetComponent<BoxCollider2D>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.size = new Vector2(550f, 50f);
				((Collider2D)component2).offset = new Vector2(250f, -25f);
			}
			((Behaviour)component).enabled = false;
			if ((Object)(object)_popupWindow != (Object)null)
			{
				component.m_popupWindow = _popupWindow;
			}
			Object.Destroy((Object)(object)component);
			return val;
		}

		private static void SetTooltip(CM_Item item, string headerKey, string? bodyKey = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			item.TooltipInfo = new TooltipInfo
			{
				PositionType = (TooltipPositionType)0,
				TooltipHeader = Loc.T(headerKey),
				TooltipText = ((bodyKey == null) ? "" : Loc.T(bodyKey)),
				UseTooptip = true
			};
			TooltipInfoLocalizer tooltipInfoLocalizer = ((Component)item).gameObject.AddComponent<TooltipInfoLocalizer>();
			if ((Object)(object)tooltipInfoLocalizer != (Object)null)
			{
				tooltipInfoLocalizer.Setup(headerKey, bodyKey);
			}
		}

		private static void AddHeader(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, Color? color = null, float heightMultiplier = 1.5f, float? fontSize = null)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey, color);
			if (!((Object)(object)val == (Object)null))
			{
				RectTransform val2 = ((Component)val).gameObject.GetComponent<RectTransform>() ?? ((Il2CppObjectBase)((Component)val).transform).TryCast<RectTransform>();
				if ((Object)(object)val2 != (Object)null)
				{
					val2.sizeDelta = new Vector2(val2.sizeDelta.x, val2.sizeDelta.y * heightMultiplier);
				}
				((Renderer)val.m_background).enabled = false;
				Transform obj = ((Component)val).transform.Find("Title/TitleText");
				TextMeshPro val3 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshPro>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					RectTransform rectTransform = ((TMP_Text)val3).rectTransform;
					rectTransform.anchorMin = Vector2.zero;
					rectTransform.anchorMax = new Vector2(1f, 0.6f);
					rectTransform.offsetMin = new Vector2(10f, 0f);
					rectTransform.offsetMax = new Vector2(0f, 0f);
					((TMP_Text)val3).alignment = (TextAlignmentOptions)1025;
					((TMP_Text)val3).fontSizeMax = fontSize ?? (((TMP_Text)val3).fontSizeMax * heightMultiplier);
				}
				BoxCollider2D component = ((Component)val).gameObject.GetComponent<BoxCollider2D>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
			}
		}

		private static BoolHandle? AddBoolToggle(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, string? descriptionKey, Func<bool> getter, Action<bool> setter)
		{
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			CM_SettingsToggleButton componentInChildren = ((Component)val).GetComponentInChildren<CM_SettingsToggleButton>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				ObjectExt.Destroy((Object)(object)componentInChildren);
			}
			(CM_Item, TextMeshPro) tuple = SetupControlButton(val, val.m_toggleInputPrefab);
			CM_Item item = tuple.Item1;
			TextMeshPro label = tuple.Item2;
			Collider2D componentInChildren2 = ((Component)item).GetComponentInChildren<Collider2D>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				((Behaviour)componentInChildren2).enabled = false;
			}
			Refresh(getter());
			if (descriptionKey != null)
			{
				SetTooltip((CM_Item)(object)val, labelKey, descriptionKey);
			}
			((CM_Item)(object)val).SetEvents(delegate
			{
				bool flag = !getter();
				setter(flag);
				Refresh(flag);
			});
			return new BoolHandle(Refresh);
			void Refresh(bool flag)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)label == (Object)null))
				{
					((TMP_Text)label).SetText(Loc.T(flag ? "ui.on" : "ui.off"), true);
					((Graphic)label).color = (flag ? Color.green : Color.red);
				}
			}
		}

		private static void AddButton(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, string? descriptionKey, string buttonTextKey, Action onClick)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey);
			if (!((Object)(object)val == (Object)null))
			{
				(CM_Item button, TextMeshPro? label) tuple = SetupControlButton(val, val.m_toggleInputPrefab);
				CM_Item item = tuple.button;
				TextMeshPro item2 = tuple.label;
				Collider2D componentInChildren = ((Component)item).GetComponentInChildren<Collider2D>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Behaviour)componentInChildren).enabled = false;
				}
				if ((Object)(object)item2 != (Object)null)
				{
					((TMP_Text)item2).SetText(Loc.T(buttonTextKey), true);
					Loc.AttachToTMP((Component)(object)item2, buttonTextKey);
					((TMP_Text)item2).fontStyle = (FontStyles)(((TMP_Text)item2).fontStyle | 4);
					((Graphic)item2).color = UIManager.AccentColor;
				}
				if (descriptionKey != null)
				{
					SetTooltip((CM_Item)(object)val, labelKey, descriptionKey);
				}
				((CM_Item)(object)val).SetEvents(delegate
				{
					onClick();
				});
			}
		}

		private static TextHandle? AddTextDisplay(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, string initialText = "")
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(val.m_toggleInputPrefab, val.m_inputAlign);
			CM_Item component = obj.GetComponent<CM_Item>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			BoxCollider2D component2 = obj.GetComponent<BoxCollider2D>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Behaviour)component2).enabled = false;
			}
			RectTransform component3 = obj.GetComponent<RectTransform>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.anchoredPosition3D = Layout.WidgetAnchorPosition;
			}
			TextMeshPro componentInChildren = obj.GetComponentInChildren<TextMeshPro>();
			if (componentInChildren != null)
			{
				((TMP_Text)componentInChildren).SetText(initialText, true);
			}
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return null;
			}
			return new TextHandle(componentInChildren);
		}

		private static TextHandle? AddTextRegion(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, Color? color = null, float heightMultiplier = 2f, float? fontSize = null)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey, color);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			RectTransform val2 = ((Component)val).gameObject.GetComponent<RectTransform>() ?? ((Il2CppObjectBase)((Component)val).transform).TryCast<RectTransform>();
			if ((Object)(object)val2 != (Object)null)
			{
				val2.sizeDelta = new Vector2(val2.sizeDelta.x, val2.sizeDelta.y * heightMultiplier);
			}
			((Renderer)val.m_background).enabled = false;
			Transform obj = ((Component)val).transform.Find("Title/TitleText");
			TextMeshPro val3 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshPro>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				RectTransform rectTransform = ((TMP_Text)val3).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = new Vector2(1f, 1f);
				rectTransform.offsetMin = new Vector2(10f, 0f);
				rectTransform.offsetMax = new Vector2(0f, 0f);
				((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			}
			BoxCollider2D component = ((Component)val).gameObject.GetComponent<BoxCollider2D>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return new TextHandle(val3);
		}

		private static EnumHandle<T>? AddEnumDropdown<T>(CM_PageSettings instance, CM_ScrollWindow window, List<iScrollWindowContent> items, string labelKey, string? descriptionKey, Func<T> getter, Action<T> setter, IReadOnlyList<(string label, T value)> options) where T : notnull
		{
			CM_SettingsItem val = CreateSettingsItem(instance, window, items, labelKey);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject popupItemPrefab;
			Transform popupAnchor;
			CM_Item button = SetupEnumButton(val, out popupItemPrefab, out popupAnchor);
			if ((Object)(object)button == (Object)null)
			{
				return null;
			}
			Refresh(getter());
			if (descriptionKey != null)
			{
				SetTooltip((CM_Item)(object)val, labelKey, descriptionKey);
			}
			((CM_Item)(object)val).SetEvents(delegate
			{
				ShowEnumPopup(getter, setter, options, button, popupItemPrefab, popupAnchor, Refresh);
			});
			return new EnumHandle<T>(Refresh);
			void Refresh(T y)
			{
				string text = y.ToString() ?? "";
				foreach (var option in options)
				{
					if (EqualityComparer<T>.Default.Equals(option.value, y))
					{
						(text, _) = option;
						break;
					}
				}
				button.SetText(text);
			}
		}

		private static void ShowEnumPopup<T>(Func<T> getter, Action<T> setter, IReadOnlyList<(string label, T value)> options, CM_Item button, GameObject popupItemPrefab, Transform? popupAnchor, Action<T> refreshButton) where T : notnull
		{
			//IL_00c6: Unknown result type (might be d

StbDxtSharp.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("StbDxtSharpTeam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("C# port of the stb_dxt.h")]
[assembly: AssemblyFileVersion("1.10.3.0")]
[assembly: AssemblyInformationalVersion("1.10.3")]
[assembly: AssemblyProduct("StbDxtSharp")]
[assembly: AssemblyTitle("StbDxtSharp")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.10.3.0")]
[module: UnverifiableCode]
namespace StbDxtSharp;

internal static class CRuntime
{
	public unsafe static void memcpy(void* a, void* b, long size)
	{
		byte* ptr = (byte*)a;
		byte* ptr2 = (byte*)b;
		for (long num = 0L; num < size; num++)
		{
			*(ptr++) = *(ptr2++);
		}
	}

	public unsafe static void memcpy(void* a, void* b, ulong size)
	{
		memcpy(a, b, (long)size);
	}

	public unsafe static void memset(void* ptr, int value, long size)
	{
		byte* ptr2 = (byte*)ptr;
		byte b = (byte)value;
		for (long num = 0L; num < size; num++)
		{
			*(ptr2++) = b;
		}
	}

	public unsafe static void memset(void* ptr, int value, ulong size)
	{
		memset(ptr, value, (long)size);
	}

	public static int abs(int v)
	{
		return Math.Abs(v);
	}

	public static float fabs(double a)
	{
		return (float)Math.Abs(a);
	}
}
[Flags]
public enum CompressionMode
{
	None = 0,
	Dithered = 1,
	HighQuality = 2
}
public static class StbDxt
{
	public static byte[] stb__Expand5 = new byte[32];

	public static byte[] stb__Expand6 = new byte[64];

	public static byte[] stb__OMatch5 = new byte[512];

	public static byte[] stb__OMatch6 = new byte[512];

	public static byte[] stb__QuantRBTab = new byte[272];

	public static byte[] stb__QuantGTab = new byte[272];

	public static int nIterPower = 4;

	public static float[] midpoints5 = new float[32]
	{
		0.015686f, 0.047059f, 0.078431f, 0.111765f, 0.145098f, 0.176471f, 0.207843f, 0.241176f, 0.27451f, 0.305882f,
		0.337255f, 0.370588f, 0.403922f, 0.435294f, 0.466667f, 0.5f, 0.533333f, 0.564706f, 0.596078f, 0.629412f,
		0.662745f, 0.694118f, 0.72549f, 0.758824f, 0.792157f, 0.823529f, 0.854902f, 0.888235f, 0.921569f, 0.952941f,
		0.984314f, 1f
	};

	public static float[] midpoints6 = new float[64]
	{
		0.007843f,
		0.023529f,
		0.039216f,
		0.054902f,
		0.070588f,
		0.086275f,
		0.101961f,
		0.117647f,
		0.133333f,
		0.14902f,
		0.164706f,
		0.180392f,
		0.196078f,
		0.211765f,
		0.227451f,
		0.245098f,
		0.262745f,
		0.278431f,
		0.294118f,
		0.309804f,
		0.32549f,
		0.341176f,
		0.356863f,
		0.372549f,
		0.388235f,
		0.403922f,
		0.419608f,
		0.435294f,
		0.45098f,
		0.466667f,
		0.482353f,
		0.5f,
		0.517647f,
		0.533333f,
		0.54902f,
		0.564706f,
		0.580392f,
		0.596078f,
		0.611765f,
		32f / 51f,
		0.643137f,
		0.658824f,
		0.67451f,
		0.690196f,
		0.705882f,
		0.721569f,
		0.737255f,
		0.754902f,
		0.772549f,
		0.788235f,
		0.803922f,
		0.819608f,
		0.835294f,
		0.85098f,
		0.866667f,
		0.882353f,
		0.898039f,
		0.913725f,
		0.929412f,
		MathF.E * 105f / 302f,
		0.960784f,
		0.976471f,
		0.992157f,
		1f
	};

	public static int[] w1Tab = new int[4] { 3, 0, 2, 1 };

	public static int[] prods = new int[4] { 589824, 2304, 262402, 66562 };

	public static int init = 1;

	public unsafe static void stb__DitherBlock(byte* dest, byte* block)
	{
		int* ptr = stackalloc int[8];
		int* ptr2 = ptr;
		int* ptr3 = ptr + 4;
		for (int i = 0; i < 3; i++)
		{
			byte* ptr4 = block + i;
			byte* ptr5 = dest + i;
			fixed (byte* ptr6 = ((i == 1) ? stb__QuantGTab : stb__QuantRBTab))
			{
				CRuntime.memset(ptr, 0, 32uL);
				for (int j = 0; j < 4; j++)
				{
					*ptr5 = ptr6[*ptr4 + (3 * ptr3[1] + 5 * *ptr3 >> 4)];
					*ptr2 = *ptr4 - *ptr5;
					ptr5[4] = ptr6[ptr4[4] + (7 * *ptr2 + 3 * ptr3[2] + 5 * ptr3[1] + *ptr3 >> 4)];
					ptr2[1] = ptr4[4] - ptr5[4];
					ptr5[8] = ptr6[ptr4[8] + (7 * ptr2[1] + 3 * ptr3[3] + 5 * ptr3[2] + ptr3[1] >> 4)];
					ptr2[2] = ptr4[8] - ptr5[8];
					ptr5[12] = ptr6[ptr4[12] + (7 * ptr2[2] + 5 * ptr3[3] + ptr3[2] >> 4)];
					ptr2[3] = ptr4[12] - ptr5[12];
					ptr4 += 16;
					ptr5 += 16;
					int* intPtr = ptr2;
					ptr2 = ptr3;
					ptr3 = intPtr;
				}
			}
		}
	}

	public unsafe static byte[] CompressDxt(int width, int height, byte[] data, bool hasAlpha, CompressionMode mode)
	{
		if (data.Length != width * height * 4)
		{
			throw new Exception("This method supports only rgba images");
		}
		int num = (hasAlpha ? 16 : 8);
		byte[] array = new byte[width * height * num / 16];
		byte* ptr = stackalloc byte[64];
		fixed (byte* ptr2 = data)
		{
			fixed (byte* ptr3 = array)
			{
				byte* ptr4 = ptr3;
				for (int i = 0; i < height; i += 4)
				{
					for (int j = 0; j < width; j += 4)
					{
						for (int k = 0; k < 4 && i + k < height; k++)
						{
							CRuntime.memcpy(ptr + k * 16, ptr2 + width * 4 * (i + k) + j * 4, 16L);
						}
						stb_compress_dxt_block(ptr4, ptr, hasAlpha ? 1 : 0, (int)mode);
						ptr4 += (hasAlpha ? 16 : 8);
					}
				}
			}
		}
		return array;
	}

	public static byte[] CompressDxt1(int width, int height, byte[] data, CompressionMode mode = CompressionMode.None)
	{
		return CompressDxt(width, height, data, hasAlpha: false, mode);
	}

	public static byte[] CompressDxt5(int width, int height, byte[] data, CompressionMode mode = CompressionMode.None)
	{
		return CompressDxt(width, height, data, hasAlpha: true, mode);
	}

	public static int stb__Mul8Bit(int a, int b)
	{
		int num = a * b + 128;
		return num + (num >> 8) >> 8;
	}

	public unsafe static void stb__From16Bit(byte* _out_, ushort v)
	{
		int num = (v & 0xF800) >> 11;
		int num2 = (v & 0x7E0) >> 5;
		int num3 = v & 0x1F;
		*_out_ = stb__Expand5[num];
		_out_[1] = stb__Expand6[num2];
		_out_[2] = stb__Expand5[num3];
		_out_[3] = 0;
	}

	public static ushort stb__As16Bit(int r, int g, int b)
	{
		return (ushort)((stb__Mul8Bit(r, 31) << 11) + (stb__Mul8Bit(g, 63) << 5) + stb__Mul8Bit(b, 31));
	}

	public static int stb__Lerp13(int a, int b)
	{
		return (2 * a + b) / 3;
	}

	public unsafe static void stb__Lerp13RGB(byte* _out_, byte* p1, byte* p2)
	{
		*_out_ = (byte)stb__Lerp13(*p1, *p2);
		_out_[1] = (byte)stb__Lerp13(p1[1], p2[1]);
		_out_[2] = (byte)stb__Lerp13(p1[2], p2[2]);
	}

	public static void stb__PrepareOptTable(byte[] Table, byte[] expand, int size)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		for (num = 0; num < 256; num++)
		{
			int num4 = 256;
			for (num2 = 0; num2 < size; num2++)
			{
				for (num3 = 0; num3 < size; num3++)
				{
					int num5 = expand[num2];
					int num6 = expand[num3];
					int num7 = CRuntime.abs(stb__Lerp13(num6, num5) - num);
					num7 += CRuntime.abs(num6 - num5) * 3 / 100;
					if (num7 < num4)
					{
						Table[num * 2] = (byte)num3;
						Table[num * 2 + 1] = (byte)num2;
						num4 = num7;
					}
				}
			}
		}
	}

	public unsafe static void stb__EvalColors(byte* color, ushort c0, ushort c1)
	{
		stb__From16Bit(color, c0);
		stb__From16Bit(color + 4, c1);
		stb__Lerp13RGB(color + 8, color, color + 4);
		stb__Lerp13RGB(color + 12, color + 4, color);
	}

	public unsafe static uint stb__MatchColorsBlock(byte* block, byte* color, int dither)
	{
		uint num = 0u;
		int num2 = *color - color[4];
		int num3 = color[1] - color[5];
		int num4 = color[2] - color[6];
		int* ptr = stackalloc int[16];
		int* ptr2 = stackalloc int[4];
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		int num8 = 0;
		for (num5 = 0; num5 < 16; num5++)
		{
			ptr[num5] = block[num5 * 4] * num2 + block[num5 * 4 + 1] * num3 + block[num5 * 4 + 2] * num4;
		}
		for (num5 = 0; num5 < 4; num5++)
		{
			ptr2[num5] = color[num5 * 4] * num2 + color[num5 * 4 + 1] * num3 + color[num5 * 4 + 2] * num4;
		}
		num6 = ptr2[1] + ptr2[3];
		num7 = ptr2[3] + ptr2[2];
		num8 = ptr2[2] + *ptr2;
		if (dither == 0)
		{
			for (num5 = 15; num5 >= 0; num5--)
			{
				int num9 = ptr[num5] * 2;
				num <<= 2;
				num = ((num9 >= num7) ? (num | (uint)((num9 < num8) ? 2 : 0)) : (num | (uint)((num9 < num6) ? 1 : 3)));
			}
		}
		else
		{
			int* ptr3 = stackalloc int[8];
			int* ptr4 = ptr3;
			int* ptr5 = ptr3 + 4;
			int* ptr6 = ptr;
			int num10 = 0;
			num6 <<= 3;
			num7 <<= 3;
			num8 <<= 3;
			for (num5 = 0; num5 < 8; num5++)
			{
				ptr3[num5] = 0;
			}
			for (num10 = 0; num10 < 4; num10++)
			{
				int num11 = 0;
				int num12 = 0;
				int num13 = 0;
				num11 = (*ptr6 << 4) + 3 * ptr5[1] + 5 * *ptr5;
				num13 = ((num11 >= num7) ? ((num11 < num8) ? 2 : 0) : ((num11 < num6) ? 1 : 3));
				*ptr4 = *ptr6 - ptr2[num13];
				num12 = num13;
				num11 = (ptr6[1] << 4) + 7 * *ptr4 + 3 * ptr5[2] + 5 * ptr5[1] + *ptr5;
				num13 = ((num11 >= num7) ? ((num11 < num8) ? 2 : 0) : ((num11 < num6) ? 1 : 3));
				ptr4[1] = ptr6[1] - ptr2[num13];
				num12 |= num13 << 2;
				num11 = (ptr6[2] << 4) + 7 * ptr4[1] + 3 * ptr5[3] + 5 * ptr5[2] + ptr5[1];
				num13 = ((num11 >= num7) ? ((num11 < num8) ? 2 : 0) : ((num11 < num6) ? 1 : 3));
				ptr4[2] = ptr6[2] - ptr2[num13];
				num12 |= num13 << 4;
				num11 = (ptr6[3] << 4) + 7 * ptr4[2] + 5 * ptr5[3] + ptr5[2];
				num13 = ((num11 >= num7) ? ((num11 < num8) ? 2 : 0) : ((num11 < num6) ? 1 : 3));
				ptr4[3] = ptr6[3] - ptr2[num13];
				num12 |= num13 << 6;
				ptr6 += 4;
				num |= (uint)(num12 << num10 * 8);
				int* intPtr = ptr4;
				ptr4 = ptr5;
				ptr5 = intPtr;
			}
		}
		return num;
	}

	public unsafe static void stb__OptimizeColorsBlock(byte* block, ushort* pmax16, ushort* pmin16)
	{
		int num = int.MaxValue;
		int num2 = -2147483647;
		byte* ptr = null;
		byte* ptr2 = null;
		double num3 = 0.0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		float* ptr3 = stackalloc float[6];
		float num7 = 0f;
		float num8 = 0f;
		float num9 = 0f;
		int* ptr4 = stackalloc int[6];
		int* ptr5 = stackalloc int[3];
		int* ptr6 = stackalloc int[3];
		int* ptr7 = stackalloc int[3];
		int num10 = 0;
		int num11 = 0;
		int num12 = 0;
		for (num10 = 0; num10 < 3; num10++)
		{
			byte* ptr8 = block + num10;
			int num13 = 0;
			int num14 = 0;
			int num15 = 0;
			num13 = (num14 = (num15 = *ptr8));
			for (num11 = 4; num11 < 64; num11 += 4)
			{
				num13 += ptr8[num11];
				if (ptr8[num11] < num14)
				{
					num14 = ptr8[num11];
				}
				else if (ptr8[num11] > num15)
				{
					num15 = ptr8[num11];
				}
			}
			ptr5[num10] = num13 + 8 >> 4;
			ptr6[num10] = num14;
			ptr7[num10] = num15;
		}
		for (num11 = 0; num11 < 6; num11++)
		{
			ptr4[num11] = 0;
		}
		for (num11 = 0; num11 < 16; num11++)
		{
			int num16 = block[num11 * 4] - *ptr5;
			int num17 = block[num11 * 4 + 1] - ptr5[1];
			int num18 = block[num11 * 4 + 2] - ptr5[2];
			*ptr4 += num16 * num16;
			ptr4[1] += num16 * num17;
			ptr4[2] += num16 * num18;
			ptr4[3] += num17 * num17;
			ptr4[4] += num17 * num18;
			ptr4[5] += num18 * num18;
		}
		for (num11 = 0; num11 < 6; num11++)
		{
			ptr3[num11] = (float)ptr4[num11] / 255f;
		}
		num7 = *ptr7 - *ptr6;
		num8 = ptr7[1] - ptr6[1];
		num9 = ptr7[2] - ptr6[2];
		for (num12 = 0; num12 < nIterPower; num12++)
		{
			float num19 = num7 * *ptr3 + num8 * ptr3[1] + num9 * ptr3[2];
			float num20 = num7 * ptr3[1] + num8 * ptr3[3] + num9 * ptr3[4];
			float num21 = num7 * ptr3[2] + num8 * ptr3[4] + num9 * ptr3[5];
			num7 = num19;
			num8 = num20;
			num9 = num21;
		}
		num3 = CRuntime.fabs(num7);
		if ((double)CRuntime.fabs(num8) > num3)
		{
			num3 = CRuntime.fabs(num8);
		}
		if ((double)CRuntime.fabs(num9) > num3)
		{
			num3 = CRuntime.fabs(num9);
		}
		if (num3 < 4.0)
		{
			num4 = 299;
			num5 = 587;
			num6 = 114;
		}
		else
		{
			num3 = 512.0 / num3;
			num4 = (int)((double)num7 * num3);
			num5 = (int)((double)num8 * num3);
			num6 = (int)((double)num9 * num3);
		}
		for (num11 = 0; num11 < 16; num11++)
		{
			int num22 = block[num11 * 4] * num4 + block[num11 * 4 + 1] * num5 + block[num11 * 4 + 2] * num6;
			if (num22 < num)
			{
				num = num22;
				ptr = block + num11 * 4;
			}
			if (num22 > num2)
			{
				num2 = num22;
				ptr2 = block + num11 * 4;
			}
		}
		*pmax16 = stb__As16Bit(*ptr2, ptr2[1], ptr2[2]);
		*pmin16 = stb__As16Bit(*ptr, ptr[1], ptr[2]);
	}

	public static ushort stb__Quantize5(float x)
	{
		ushort num = 0;
		x = ((x < 0f) ? 0f : ((x > 1f) ? 1f : x));
		num = (ushort)(x * 31f);
		return (ushort)(num + (ushort)((x > midpoints5[num]) ? 1 : 0));
	}

	public static ushort stb__Quantize6(float x)
	{
		ushort num = 0;
		x = ((x < 0f) ? 0f : ((x > 1f) ? 1f : x));
		num = (ushort)(x * 63f);
		return (ushort)(num + (ushort)((x > midpoints6[num]) ? 1 : 0));
	}

	public unsafe static int stb__RefineBlock(byte* block, ushort* pmax16, ushort* pmin16, uint mask)
	{
		float num = 0f;
		ushort num2 = 0;
		ushort num3 = 0;
		ushort num4 = 0;
		ushort num5 = 0;
		int num6 = 0;
		int num7 = 0;
		int num8 = 0;
		int num9 = 0;
		int num10 = 0;
		int num11 = 0;
		int num12 = 0;
		int num13 = 0;
		int num14 = 0;
		int num15 = 0;
		int num16 = 0;
		uint num17 = mask;
		num2 = *pmin16;
		num3 = *pmax16;
		if ((mask ^ (mask << 2)) < 4)
		{
			int num18 = 8;
			int num19 = 8;
			int num20 = 8;
			for (num6 = 0; num6 < 16; num6++)
			{
				num18 += block[num6 * 4];
				num19 += block[num6 * 4 + 1];
				num20 += block[num6 * 4 + 2];
			}
			num18 >>= 4;
			num19 >>= 4;
			num20 >>= 4;
			num5 = (ushort)((stb__OMatch5[num18 * 2] << 11) | (stb__OMatch6[num19 * 2] << 5) | stb__OMatch5[num20 * 2]);
			num4 = (ushort)((stb__OMatch5[num18 * 2 + 1] << 11) | (stb__OMatch6[num19 * 2 + 1] << 5) | stb__OMatch5[num20 * 2 + 1]);
		}
		else
		{
			num11 = (num12 = (num13 = 0));
			num14 = (num15 = (num16 = 0));
			num6 = 0;
			while (num6 < 16)
			{
				int num21 = (int)(num17 & 3);
				int num22 = w1Tab[num21];
				int num23 = block[num6 * 4];
				int num24 = block[num6 * 4 + 1];
				int num25 = block[num6 * 4 + 2];
				num7 += prods[num21];
				num11 += num22 * num23;
				num12 += num22 * num24;
				num13 += num22 * num25;
				num14 += num23;
				num15 += num24;
				num16 += num25;
				num6++;
				num17 >>= 2;
			}
			num14 = 3 * num14 - num11;
			num15 = 3 * num15 - num12;
			num16 = 3 * num16 - num13;
			num8 = num7 >> 16;
			num10 = (num7 >> 8) & 0xFF;
			num9 = num7 & 0xFF;
			num = 1f / 85f / (float)(num8 * num10 - num9 * num9);
			num5 = (ushort)(stb__Quantize5((float)(num11 * num10 - num14 * num9) * num) << 11);
			num5 |= (ushort)(stb__Quantize6((float)(num12 * num10 - num15 * num9) * num) << 5);
			num5 |= stb__Quantize5((float)(num13 * num10 - num16 * num9) * num);
			num4 = (ushort)(stb__Quantize5((float)(num14 * num8 - num11 * num9) * num) << 11);
			num4 |= (ushort)(stb__Quantize6((float)(num15 * num8 - num12 * num9) * num) << 5);
			num4 |= stb__Quantize5((float)(num16 * num8 - num13 * num9) * num);
		}
		*pmin16 = num4;
		*pmax16 = num5;
		if (num2 == num4 && num3 == num5)
		{
			return 0;
		}
		return 1;
	}

	public unsafe static void stb__CompressColorBlock(byte* dest, byte* block, int mode)
	{
		uint num = 0u;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		ushort num5 = 0;
		ushort num6 = 0;
		byte* ptr = stackalloc byte[64];
		byte* color = stackalloc byte[16];
		num3 = mode & 1;
		num4 = (((mode & 2) == 0) ? 1 : 2);
		for (num2 = 1; num2 < 16 && ((uint*)block)[num2] == *(uint*)block; num2++)
		{
		}
		if (num2 == 16)
		{
			int num7 = *block;
			int num8 = block[1];
			int num9 = block[2];
			num = 2863311530u;
			num5 = (ushort)((stb__OMatch5[num7 * 2] << 11) | (stb__OMatch6[num8 * 2] << 5) | stb__OMatch5[num9 * 2]);
			num6 = (ushort)((stb__OMatch5[num7 * 2 + 1] << 11) | (stb__OMatch6[num8 * 2 + 1] << 5) | stb__OMatch5[num9 * 2 + 1]);
		}
		else
		{
			if (num3 != 0)
			{
				stb__DitherBlock(ptr, block);
			}
			stb__OptimizeColorsBlock((num3 != 0) ? ptr : block, &num5, &num6);
			if (num5 != num6)
			{
				stb__EvalColors(color, num5, num6);
				num = stb__MatchColorsBlock(block, color, num3);
			}
			else
			{
				num = 0u;
			}
			for (num2 = 0; num2 < num4; num2++)
			{
				uint num10 = num;
				if (stb__RefineBlock((num3 != 0) ? ptr : block, &num5, &num6, num) != 0)
				{
					if (num5 == num6)
					{
						num = 0u;
						break;
					}
					stb__EvalColors(color, num5, num6);
					num = stb__MatchColorsBlock(block, color, num3);
				}
				if (num == num10)
				{
					break;
				}
			}
		}
		if (num5 < num6)
		{
			ushort num11 = num6;
			num6 = num5;
			num5 = num11;
			num ^= 0x55555555;
		}
		*dest = (byte)num5;
		dest[1] = (byte)(num5 >> 8);
		dest[2] = (byte)num6;
		dest[3] = (byte)(num6 >> 8);
		dest[4] = (byte)num;
		dest[5] = (byte)(num >> 8);
		dest[6] = (byte)(num >> 16);
		dest[7] = (byte)(num >> 24);
	}

	public unsafe static void stb__CompressAlphaBlock(byte* dest, byte* src, int stride)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		int num8 = 0;
		int num9 = 0;
		num8 = (num9 = *src);
		for (num = 1; num < 16; num++)
		{
			if (src[num * stride] < num8)
			{
				num8 = src[num * stride];
			}
			else if (src[num * stride] > num9)
			{
				num9 = src[num * stride];
			}
		}
		*dest = (byte)num9;
		dest[1] = (byte)num8;
		dest += 2;
		num2 = num9 - num8;
		num4 = num2 * 4;
		num5 = num2 * 2;
		num3 = ((num2 < 8) ? (num2 - 1) : (num2 / 2 + 2));
		num3 -= num8 * 7;
		num6 = 0;
		num7 = 0;
		for (num = 0; num < 16; num++)
		{
			int num10 = src[num * stride] * 7 + num3;
			int num11 = 0;
			int num12 = 0;
			num12 = ((num10 >= num4) ? (-1) : 0);
			num11 = num12 & 4;
			num10 -= num4 & num12;
			num12 = ((num10 >= num5) ? (-1) : 0);
			num11 += num12 & 2;
			num10 -= num5 & num12;
			num11 += ((num10 >= num2) ? 1 : 0);
			num11 = -num11 & 7;
			num11 ^= ((2 > num11) ? 1 : 0);
			num7 |= num11 << num6;
			if ((num6 += 3) >= 8)
			{
				*(dest++) = (byte)num7;
				num7 >>= 8;
				num6 -= 8;
			}
		}
	}

	public static void stb__InitDXT()
	{
		int num = 0;
		for (num = 0; num < 32; num++)
		{
			stb__Expand5[num] = (byte)((num << 3) | (num >> 2));
		}
		for (num = 0; num < 64; num++)
		{
			stb__Expand6[num] = (byte)((num << 2) | (num >> 4));
		}
		for (num = 0; num < 272; num++)
		{
			int a = ((num - 8 >= 0) ? ((num - 8 > 255) ? 255 : (num - 8)) : 0);
			stb__QuantRBTab[num] = stb__Expand5[stb__Mul8Bit(a, 31)];
			stb__QuantGTab[num] = stb__Expand6[stb__Mul8Bit(a, 63)];
		}
		stb__PrepareOptTable(stb__OMatch5, stb__Expand5, 32);
		stb__PrepareOptTable(stb__OMatch6, stb__Expand6, 64);
	}

	public unsafe static void stb_compress_dxt_block(byte* dest, byte* src, int alpha, int mode)
	{
		byte* ptr = stackalloc byte[64];
		if (init != 0)
		{
			stb__InitDXT();
			init = 0;
		}
		if (alpha != 0)
		{
			int num = 0;
			stb__CompressAlphaBlock(dest, src + 3, 4);
			dest += 8;
			CRuntime.memcpy(ptr, src, 64uL);
			for (num = 0; num < 16; num++)
			{
				ptr[num * 4 + 3] = byte.MaxValue;
			}
			src = ptr;
		}
		stb__CompressColorBlock(dest, src, mode);
	}

	public unsafe static void stb_compress_bc4_block(byte* dest, byte* src)
	{
		stb__CompressAlphaBlock(dest, src, 1);
	}

	public unsafe static void stb_compress_bc5_block(byte* dest, byte* src)
	{
		stb__CompressAlphaBlock(dest, src, 2);
		stb__CompressAlphaBlock(dest + 8, src + 1, 2);
	}
}

StbImageSharp.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using StbImageSharp.Hebron.Runtime;

[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("StbImageSharpTeam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("C# port of the stb_image.h")]
[assembly: AssemblyFileVersion("2.30.16.0")]
[assembly: AssemblyInformationalVersion("2.30.16+125af70cb557033f2c46aec8e82eaaf72ac49817")]
[assembly: AssemblyProduct("StbImageSharp")]
[assembly: AssemblyTitle("StbImageSharp")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.30.16.0")]
[module: UnverifiableCode]
namespace StbImageSharp
{
	public class AnimatedFrameResult : ImageResult
	{
		public int DelayInMs { get; set; }
	}
	internal class AnimatedGifEnumerator : IEnumerator<AnimatedFrameResult>, IEnumerator, IDisposable
	{
		private readonly StbImage.stbi__context _context;

		private StbImage.stbi__gif _gif;

		private readonly ColorComponents _colorComponents;

		public ColorComponents ColorComponents => _colorComponents;

		public AnimatedFrameResult Current { get; private set; }

		object IEnumerator.Current => Current;

		public AnimatedGifEnumerator(Stream input, ColorComponents colorComponents)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			_context = new StbImage.stbi__context(input);
			if (StbImage.stbi__gif_test(_context) == 0)
			{
				throw new Exception("Input stream is not GIF file.");
			}
			_gif = new StbImage.stbi__gif();
			_colorComponents = colorComponents;
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		public unsafe bool MoveNext()
		{
			int num = default(int);
			byte b = default(byte);
			byte* ptr = StbImage.stbi__gif_load_next(_context, _gif, &num, (int)ColorComponents, &b);
			if (ptr == null)
			{
				return false;
			}
			if (Current == null)
			{
				Current = new AnimatedFrameResult
				{
					Width = _gif.w,
					Height = _gif.h,
					SourceComp = (ColorComponents)num,
					Comp = ((ColorComponents == ColorComponents.Default) ? ((ColorComponents)num) : ColorComponents)
				};
				Current.Data = new byte[Current.Width * Current.Height * (int)Current.Comp];
			}
			Current.DelayInMs = _gif.delay;
			Marshal.Copy(new IntPtr(ptr), Current.Data, 0, Current.Data.Length);
			return true;
		}

		public void Reset()
		{
			throw new NotImplementedException();
		}

		~AnimatedGifEnumerator()
		{
			Dispose(disposing: false);
		}

		protected unsafe virtual void Dispose(bool disposing)
		{
			if (_gif != null)
			{
				if (_gif._out_ != null)
				{
					CRuntime.free(_gif._out_);
					_gif._out_ = null;
				}
				if (_gif.history != null)
				{
					CRuntime.free(_gif.history);
					_gif.history = null;
				}
				if (_gif.background != null)
				{
					CRuntime.free(_gif.background);
					_gif.background = null;
				}
				_gif = null;
			}
		}
	}
	internal class AnimatedGifEnumerable : IEnumerable<AnimatedFrameResult>, IEnumerable
	{
		private readonly Stream _input;

		private readonly ColorComponents _colorComponents;

		public ColorComponents ColorComponents => _colorComponents;

		public AnimatedGifEnumerable(Stream input, ColorComponents colorComponents)
		{
			_input = input;
			_colorComponents = colorComponents;
		}

		public IEnumerator<AnimatedFrameResult> GetEnumerator()
		{
			return new AnimatedGifEnumerator(_input, ColorComponents);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public enum ColorComponents
	{
		Default,
		Grey,
		GreyAlpha,
		RedGreenBlue,
		RedGreenBlueAlpha
	}
	public struct ImageInfo
	{
		public int Width;

		public int Height;

		public ColorComponents ColorComponents;

		public int BitsPerChannel;

		public unsafe static ImageInfo? FromStream(Stream stream)
		{
			StbImage.stbi__context s = new StbImage.stbi__context(stream);
			bool flag = StbImage.stbi__is_16_main(s) == 1;
			StbImage.stbi__rewind(s);
			int width = default(int);
			int height = default(int);
			int colorComponents = default(int);
			int num = StbImage.stbi__info_main(s, &width, &height, &colorComponents);
			StbImage.stbi__rewind(s);
			if (num == 0)
			{
				return null;
			}
			return new ImageInfo
			{
				Width = width,
				Height = height,
				ColorComponents = (ColorComponents)colorComponents,
				BitsPerChannel = (flag ? 16 : 8)
			};
		}
	}
	public class ImageResult
	{
		public int Width { get; set; }

		public int Height { get; set; }

		public ColorComponents SourceComp { get; set; }

		public ColorComponents Comp { get; set; }

		public byte[] Data { get; set; }

		internal unsafe static ImageResult FromResult(byte* result, int width, int height, ColorComponents comp, ColorComponents req_comp)
		{
			if (result == null)
			{
				throw new InvalidOperationException(StbImage.stbi__g_failure_reason);
			}
			ImageResult imageResult = new ImageResult
			{
				Width = width,
				Height = height,
				SourceComp = comp,
				Comp = ((req_comp == ColorComponents.Default) ? comp : req_comp)
			};
			imageResult.Data = new byte[width * height * (int)imageResult.Comp];
			Marshal.Copy(new IntPtr(result), imageResult.Data, 0, imageResult.Data.Length);
			return imageResult;
		}

		public unsafe static ImageResult FromStream(Stream stream, ColorComponents requiredComponents = ColorComponents.Default)
		{
			byte* ptr = null;
			try
			{
				int width = default(int);
				int height = default(int);
				int comp = default(int);
				ptr = StbImage.stbi__load_and_postprocess_8bit(new StbImage.stbi__context(stream), &width, &height, &comp, (int)requiredComponents);
				return FromResult(ptr, width, height, (ColorComponents)comp, requiredComponents);
			}
			finally
			{
				if (ptr != null)
				{
					CRuntime.free(ptr);
				}
			}
		}

		public static ImageResult FromMemory(byte[] data, ColorComponents requiredComponents = ColorComponents.Default)
		{
			using MemoryStream stream = new MemoryStream(data);
			return FromStream(stream, requiredComponents);
		}

		public static IEnumerable<AnimatedFrameResult> AnimatedGifFramesFromStream(Stream stream, ColorComponents requiredComponents = ColorComponents.Default)
		{
			return new AnimatedGifEnumerable(stream, requiredComponents);
		}
	}
	public class ImageResultFloat
	{
		public int Width { get; set; }

		public int Height { get; set; }

		public ColorComponents SourceComp { get; set; }

		public ColorComponents Comp { get; set; }

		public float[] Data { get; set; }

		internal unsafe static ImageResultFloat FromResult(float* result, int width, int height, ColorComponents comp, ColorComponents req_comp)
		{
			if (result == null)
			{
				throw new InvalidOperationException(StbImage.stbi__g_failure_reason);
			}
			ImageResultFloat imageResultFloat = new ImageResultFloat
			{
				Width = width,
				Height = height,
				SourceComp = comp,
				Comp = ((req_comp == ColorComponents.Default) ? comp : req_comp)
			};
			imageResultFloat.Data = new float[width * height * (int)imageResultFloat.Comp];
			Marshal.Copy(new IntPtr(result), imageResultFloat.Data, 0, imageResultFloat.Data.Length);
			return imageResultFloat;
		}

		public unsafe static ImageResultFloat FromStream(Stream stream, ColorComponents requiredComponents = ColorComponents.Default)
		{
			float* ptr = null;
			try
			{
				int width = default(int);
				int height = default(int);
				int comp = default(int);
				ptr = StbImage.stbi__loadf_main(new StbImage.stbi__context(stream), &width, &height, &comp, (int)requiredComponents);
				return FromResult(ptr, width, height, (ColorComponents)comp, requiredComponents);
			}
			finally
			{
				if (ptr != null)
				{
					CRuntime.free(ptr);
				}
			}
		}

		public static ImageResultFloat FromMemory(byte[] data, ColorComponents requiredComponents = ColorComponents.Default)
		{
			using MemoryStream stream = new MemoryStream(data);
			return FromStream(stream, requiredComponents);
		}
	}
	public static class StbImage
	{
		public class stbi__context
		{
			private readonly Stream _stream;

			public byte[] _tempBuffer;

			public int img_n;

			public int img_out_n;

			public uint img_x;

			public uint img_y;

			public Stream Stream => _stream;

			public stbi__context(Stream stream)
			{
				if (stream == null)
				{
					throw new ArgumentNullException("stream");
				}
				_stream = stream;
			}
		}

		public struct stbi__bmp_data
		{
			public int bpp;

			public int offset;

			public int hsz;

			public uint mr;

			public uint mg;

			public uint mb;

			public uint ma;

			public uint all_a;

			public int extra_read;
		}

		public struct stbi__result_info
		{
			public int bits_per_channel;

			public int num_channels;

			public int channel_order;
		}

		public class stbi__gif
		{
			public unsafe byte* _out_;

			public unsafe byte* background;

			public int bgindex;

			public stbi__gif_lzw[] codes = new stbi__gif_lzw[8192];

			public byte[][] color_table;

			public int cur_x;

			public int cur_y;

			public int delay;

			public int eflags;

			public int flags;

			public int h;

			public unsafe byte* history;

			public int lflags;

			public int line_size;

			public byte[][] lpal = Utility.CreateArray<byte>(256, 4);

			public int max_x;

			public int max_y;

			public byte[][] pal = Utility.CreateArray<byte>(256, 4);

			public int parse;

			public int ratio;

			public int start_x;

			public int start_y;

			public int step;

			public int transparent;

			public int w;
		}

		public struct stbi__gif_lzw
		{
			public short prefix;

			public byte first;

			public byte suffix;
		}

		public unsafe delegate void delegate0(byte* arg0, int arg1, short* arg2);

		public unsafe delegate void delegate1(byte* arg0, byte* arg1, byte* arg2, byte* arg3, int arg4, int arg5);

		public unsafe delegate byte* delegate2(byte* arg0, byte* arg1, byte* arg2, int arg3, int arg4);

		public struct stbi__huffman
		{
			public unsafe fixed byte fast[512];

			public unsafe fixed ushort code[256];

			public unsafe fixed byte values[256];

			public unsafe fixed byte size[257];

			public unsafe fixed uint maxcode[18];

			public unsafe fixed int delta[17];
		}

		public class stbi__jpeg
		{
			public struct unnamed1
			{
				public int id;

				public int h;

				public int v;

				public int tq;

				public int hd;

				public int ha;

				public int dc_pred;

				public int x;

				public int y;

				public int w2;

				public int h2;

				public unsafe byte* data;

				public unsafe void* raw_data;

				public unsafe void* raw_coeff;

				public unsafe byte* linebuf;

				public unsafe short* coeff;

				public int coeff_w;

				public int coeff_h;
			}

			public int app14_color_transform;

			public int code_bits;

			public uint code_buffer;

			public ushort[][] dequant = Utility.CreateArray<ushort>(4, 64);

			public int eob_run;

			public short[][] fast_ac = Utility.CreateArray<short>(4, 512);

			public stbi__huffman[] huff_ac = new stbi__huffman[4];

			public stbi__huffman[] huff_dc = new stbi__huffman[4];

			public delegate0 idct_block_kernel;

			public unnamed1[] img_comp = new unnamed1[4];

			public int img_h_max;

			public int img_mcu_h;

			public int img_mcu_w;

			public int img_mcu_x;

			public int img_mcu_y;

			public int img_v_max;

			public int jfif;

			public byte marker;

			public int nomore;

			public int[] order = new int[4];

			public int progressive;

			public delegate2 resample_row_hv_2_kernel;

			public int restart_interval;

			public int rgb;

			public stbi__context s;

			public int scan_n;

			public int spec_end;

			public int spec_start;

			public int succ_high;

			public int succ_low;

			public int todo;

			public delegate1 YCbCr_to_RGB_kernel;
		}

		public class stbi__resample
		{
			public int hs;

			public unsafe byte* line0;

			public unsafe byte* line1;

			public delegate2 resample;

			public int vs;

			public int w_lores;

			public int ypos;

			public int ystep;
		}

		public class stbi__png
		{
			public unsafe byte* _out_;

			public int depth;

			public unsafe byte* expanded;

			public unsafe byte* idata;

			public stbi__context s;
		}

		public struct stbi__pngchunk
		{
			public uint length;

			public uint type;
		}

		public struct stbi__zbuf
		{
			public unsafe byte* zbuffer;

			public unsafe byte* zbuffer_end;

			public int num_bits;

			public int hit_zeof_once;

			public uint code_buffer;

			public unsafe sbyte* zout;

			public unsafe sbyte* zout_start;

			public unsafe sbyte* zout_end;

			public int z_expandable;

			public stbi__zhuffman z_length;

			public stbi__zhuffman z_distance;
		}

		public struct stbi__zhuffman
		{
			public unsafe fixed ushort fast[512];

			public unsafe fixed ushort firstcode[16];

			public unsafe fixed int maxcode[17];

			public unsafe fixed ushort firstsymbol[16];

			public unsafe fixed byte size[288];

			public unsafe fixed ushort value[288];
		}

		public static string stbi__g_failure_reason;

		public static readonly char[] stbi__parse_png_file_invalid_chunk = new char[25];

		public const int STBI_default = 0;

		public const int STBI_grey = 1;

		public const int STBI_grey_alpha = 2;

		public const int STBI_rgb = 3;

		public const int STBI_rgb_alpha = 4;

		public const int STBI_ORDER_RGB = 0;

		public const int STBI_ORDER_BGR = 1;

		public const int STBI__SCAN_load = 0;

		public const int STBI__SCAN_type = 1;

		public const int STBI__SCAN_header = 2;

		public static int stbi__vertically_flip_on_load_global;

		public static int stbi__vertically_flip_on_load_local;

		public static int stbi__vertically_flip_on_load_set;

		public static float stbi__l2h_gamma = 2.2f;

		public static float stbi__l2h_scale = 1f;

		public static float stbi__h2l_gamma_i = 0.45454544f;

		public static float stbi__h2l_scale_i = 1f;

		public static int stbi__unpremultiply_on_load_global;

		public static int stbi__de_iphone_flag_global;

		public static int stbi__unpremultiply_on_load_local;

		public static int stbi__unpremultiply_on_load_set;

		public static int stbi__de_iphone_flag_local;

		public static int stbi__de_iphone_flag_set;

		public static byte[] stbi__process_marker_tag = new byte[6] { 65, 100, 111, 98, 101, 0 };

		public static byte[] stbi__process_frame_header_rgb = new byte[3] { 82, 71, 66 };

		public static byte[] stbi__compute_huffman_codes_length_dezigzag = new byte[19]
		{
			16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
			11, 4, 12, 3, 13, 2, 14, 1, 15
		};

		public static int[] stbi__shiftsigned_mul_table = new int[9] { 0, 255, 85, 73, 17, 33, 65, 129, 1 };

		public static int[] stbi__shiftsigned_shift_table = new int[9] { 0, 0, 0, 1, 0, 2, 4, 6, 0 };

		public static uint[] stbi__bmask = new uint[17]
		{
			0u, 1u, 3u, 7u, 15u, 31u, 63u, 127u, 255u, 511u,
			1023u, 2047u, 4095u, 8191u, 16383u, 32767u, 65535u
		};

		public static int[] stbi__jbias = new int[16]
		{
			0, -1, -3, -7, -15, -31, -63, -127, -255, -511,
			-1023, -2047, -4095, -8191, -16383, -32767
		};

		public static byte[] stbi__jpeg_dezigzag = new byte[79]
		{
			0, 1, 8, 16, 9, 2, 3, 10, 17, 24,
			32, 25, 18, 11, 4, 5, 12, 19, 26, 33,
			40, 48, 41, 34, 27, 20, 13, 6, 7, 14,
			21, 28, 35, 42, 49, 56, 57, 50, 43, 36,
			29, 22, 15, 23, 30, 37, 44, 51, 58, 59,
			52, 45, 38, 31, 39, 46, 53, 60, 61, 54,
			47, 55, 62, 63, 63, 63, 63, 63, 63, 63,
			63, 63, 63, 63, 63, 63, 63, 63, 63
		};

		public const int STBI__F_none = 0;

		public const int STBI__F_sub = 1;

		public const int STBI__F_up = 2;

		public const int STBI__F_avg = 3;

		public const int STBI__F_paeth = 4;

		public const int STBI__F_avg_first = 5;

		public static byte[] first_row_filter = new byte[5] { 0, 1, 0, 5, 1 };

		public static byte[] stbi__check_png_header_png_sig = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };

		public static byte[] stbi__depth_scale_table = new byte[9] { 0, 255, 85, 0, 17, 0, 0, 0, 1 };

		public static byte[] stbi__zdefault_distance = new byte[32]
		{
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5
		};

		public static byte[] stbi__zdefault_length = new byte[288]
		{
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
			8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
			9, 9, 9, 9, 9, 9, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			8, 8, 8, 8, 8, 8, 8, 8
		};

		public static int[] stbi__zdist_base = new int[32]
		{
			1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
			33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
			1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
			0, 0
		};

		public static int[] stbi__zdist_extra = new int[32]
		{
			0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
			4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
			9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
			0, 0
		};

		public static int[] stbi__zlength_base = new int[31]
		{
			3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
			15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
			67, 83, 99, 115, 131, 163, 195, 227, 258, 0,
			0
		};

		public static int[] stbi__zlength_extra = new int[31]
		{
			0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
			1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
			4, 4, 4, 4, 5, 5, 5, 5, 0, 0,
			0
		};

		public static int NativeAllocations => MemoryStats.Allocations;

		private static int stbi__err(string str)
		{
			stbi__g_failure_reason = str;
			return 0;
		}

		public static byte stbi__get8(stbi__context s)
		{
			int num = s.Stream.ReadByte();
			if (num == -1)
			{
				return 0;
			}
			return (byte)num;
		}

		public static void stbi__skip(stbi__context s, int skip)
		{
			s.Stream.Seek(skip, SeekOrigin.Current);
		}

		public static void stbi__rewind(stbi__context s)
		{
			s.Stream.Seek(0L, SeekOrigin.Begin);
		}

		public static int stbi__at_eof(stbi__context s)
		{
			return (s.Stream.Position == s.Stream.Length) ? 1 : 0;
		}

		public unsafe static int stbi__getn(stbi__context s, byte* buf, int size)
		{
			if (s._tempBuffer == null || s._tempBuffer.Length < size)
			{
				s._tempBuffer = new byte[size * 2];
			}
			int num = s.Stream.Read(s._tempBuffer, 0, size);
			Marshal.Copy(s._tempBuffer, 0, new IntPtr(buf), num);
			return num;
		}

		public static int stbi__bmp_test(stbi__context s)
		{
			int result = stbi__bmp_test_raw(s);
			stbi__rewind(s);
			return result;
		}

		public unsafe static void* stbi__bmp_load(stbi__context s, int* x, int* y, int* comp, int req_comp, stbi__result_info* ri)
		{
			uint num = 0u;
			uint num2 = 0u;
			uint num3 = 0u;
			uint num4 = 0u;
			uint num5 = 0u;
			byte[][] array = Utility.CreateArray<byte>(256, 4);
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = 0;
			int num10 = 0;
			int num11 = 0;
			int num12 = 0;
			stbi__bmp_data stbi__bmp_data = new stbi__bmp_data
			{
				all_a = 255u
			};
			if (stbi__bmp_parse_header(s, &stbi__bmp_data) == null)
			{
				return null;
			}
			num10 = (((int)s.img_y > 0) ? 1 : 0);
			s.img_y = (uint)CRuntime.abs((int)s.img_y);
			if (s.img_y > 16777216)
			{
				return (void*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			if (s.img_x > 16777216)
			{
				return (void*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			num = stbi__bmp_data.mr;
			num2 = stbi__bmp_data.mg;
			num3 = stbi__bmp_data.mb;
			num4 = stbi__bmp_data.ma;
			num5 = stbi__bmp_data.all_a;
			if (stbi__bmp_data.hsz == 12)
			{
				if (stbi__bmp_data.bpp < 24)
				{
					num6 = (stbi__bmp_data.offset - stbi__bmp_data.extra_read - 24) / 3;
				}
			}
			else if (stbi__bmp_data.bpp < 16)
			{
				num6 = stbi__bmp_data.offset - stbi__bmp_data.extra_read - stbi__bmp_data.hsz >> 2;
			}
			if (num6 == 0)
			{
				int num13 = (int)s.Stream.Position;
				int num14 = 1024;
				int num15 = 1024;
				if (num13 <= 0 || num13 > num14)
				{
					return (void*)(int)((stbi__err("bad header") != 0) ? 0u : 0u);
				}
				if (stbi__bmp_data.offset < num13 || stbi__bmp_data.offset - num13 > num15)
				{
					return (void*)(int)((stbi__err("bad offset") != 0) ? 0u : 0u);
				}
				stbi__skip(s, stbi__bmp_data.offset - num13);
			}
			if (stbi__bmp_data.bpp == 24 && num4 == 4278190080u)
			{
				s.img_n = 3;
			}
			else
			{
				s.img_n = ((num4 != 0) ? 4 : 3);
			}
			num12 = ((req_comp == 0 || req_comp < 3) ? s.img_n : req_comp);
			if (stbi__mad3sizes_valid(num12, (int)s.img_x, (int)s.img_y, 0) == 0)
			{
				return (void*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			byte* ptr = (byte*)stbi__malloc_mad3(num12, (int)s.img_x, (int)s.img_y, 0);
			if (ptr == null)
			{
				return (void*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			if (stbi__bmp_data.bpp < 16)
			{
				int num16 = 0;
				if (num6 == 0 || num6 > 256)
				{
					CRuntime.free(ptr);
					return (void*)(int)((stbi__err("invalid") != 0) ? 0u : 0u);
				}
				for (num7 = 0; num7 < num6; num7++)
				{
					array[num7][2] = stbi__get8(s);
					array[num7][1] = stbi__get8(s);
					array[num7][0] = stbi__get8(s);
					if (stbi__bmp_data.hsz != 12)
					{
						stbi__get8(s);
					}
					array[num7][3] = byte.MaxValue;
				}
				stbi__skip(s, stbi__bmp_data.offset - stbi__bmp_data.extra_read - stbi__bmp_data.hsz - num6 * ((stbi__bmp_data.hsz == 12) ? 3 : 4));
				if (stbi__bmp_data.bpp == 1)
				{
					num9 = (int)(s.img_x + 7 >> 3);
				}
				else if (stbi__bmp_data.bpp == 4)
				{
					num9 = (int)(s.img_x + 1 >> 1);
				}
				else
				{
					if (stbi__bmp_data.bpp != 8)
					{
						CRuntime.free(ptr);
						return (void*)(int)((stbi__err("bad bpp") != 0) ? 0u : 0u);
					}
					num9 = (int)s.img_x;
				}
				num11 = -num9 & 3;
				if (stbi__bmp_data.bpp == 1)
				{
					for (num8 = 0; num8 < (int)s.img_y; num8++)
					{
						int num17 = 7;
						int num18 = stbi__get8(s);
						for (num7 = 0; num7 < (int)s.img_x; num7++)
						{
							int num19 = (num18 >> num17) & 1;
							ptr[num16++] = array[num19][0];
							ptr[num16++] = array[num19][1];
							ptr[num16++] = array[num19][2];
							if (num12 == 4)
							{
								ptr[num16++] = byte.MaxValue;
							}
							if (num7 + 1 == (int)s.img_x)
							{
								break;
							}
							if (--num17 < 0)
							{
								num17 = 7;
								num18 = stbi__get8(s);
							}
						}
						stbi__skip(s, num11);
					}
				}
				else
				{
					for (num8 = 0; num8 < (int)s.img_y; num8++)
					{
						for (num7 = 0; num7 < (int)s.img_x; num7 += 2)
						{
							int num20 = stbi__get8(s);
							int num21 = 0;
							if (stbi__bmp_data.bpp == 4)
							{
								num21 = num20 & 0xF;
								num20 >>= 4;
							}
							ptr[num16++] = array[num20][0];
							ptr[num16++] = array[num20][1];
							ptr[num16++] = array[num20][2];
							if (num12 == 4)
							{
								ptr[num16++] = byte.MaxValue;
							}
							if (num7 + 1 == (int)s.img_x)
							{
								break;
							}
							num20 = ((stbi__bmp_data.bpp == 8) ? stbi__get8(s) : num21);
							ptr[num16++] = array[num20][0];
							ptr[num16++] = array[num20][1];
							ptr[num16++] = array[num20][2];
							if (num12 == 4)
							{
								ptr[num16++] = byte.MaxValue;
							}
						}
						stbi__skip(s, num11);
					}
				}
			}
			else
			{
				int shift = 0;
				int shift2 = 0;
				int shift3 = 0;
				int shift4 = 0;
				int num22 = 0;
				int num23 = 0;
				int num24 = 0;
				int num25 = 0;
				int num26 = 0;
				int num27 = 0;
				stbi__skip(s, stbi__bmp_data.offset - stbi__bmp_data.extra_read - stbi__bmp_data.hsz);
				num9 = (int)((stbi__bmp_data.bpp == 24) ? (3 * s.img_x) : ((stbi__bmp_data.bpp == 16) ? (2 * s.img_x) : 0));
				num11 = -num9 & 3;
				if (stbi__bmp_data.bpp == 24)
				{
					num27 = 1;
				}
				else if (stbi__bmp_data.bpp == 32 && num3 == 255 && num2 == 65280 && num == 16711680 && num4 == 4278190080u)
				{
					num27 = 2;
				}
				if (num27 == 0)
				{
					if (num == 0 || num2 == 0 || num3 == 0)
					{
						CRuntime.free(ptr);
						return (void*)(int)((stbi__err("bad masks") != 0) ? 0u : 0u);
					}
					shift = stbi__high_bit(num) - 7;
					num22 = stbi__bitcount(num);
					shift2 = stbi__high_bit(num2) - 7;
					num23 = stbi__bitcount(num2);
					shift3 = stbi__high_bit(num3) - 7;
					num24 = stbi__bitcount(num3);
					shift4 = stbi__high_bit(num4) - 7;
					num25 = stbi__bitcount(num4);
					if (num22 > 8 || num23 > 8 || num24 > 8 || num25 > 8)
					{
						CRuntime.free(ptr);
						return (void*)(int)((stbi__err("bad masks") != 0) ? 0u : 0u);
					}
				}
				for (num8 = 0; num8 < (int)s.img_y; num8++)
				{
					if (num27 != 0)
					{
						for (num7 = 0; num7 < (int)s.img_x; num7++)
						{
							byte b = 0;
							ptr[num26 + 2] = stbi__get8(s);
							ptr[num26 + 1] = stbi__get8(s);
							ptr[num26] = stbi__get8(s);
							num26 += 3;
							b = ((num27 == 2) ? stbi__get8(s) : byte.MaxValue);
							num5 |= b;
							if (num12 == 4)
							{
								ptr[num26++] = b;
							}
						}
					}
					else
					{
						int bpp = stbi__bmp_data.bpp;
						for (num7 = 0; num7 < (int)s.img_x; num7++)
						{
							uint num28 = ((bpp == 16) ? ((uint)stbi__get16le(s)) : stbi__get32le(s));
							uint num29 = 0u;
							ptr[num26++] = (byte)(stbi__shiftsigned(num28 & num, shift, num22) & 0xFF);
							ptr[num26++] = (byte)(stbi__shiftsigned(num28 & num2, shift2, num23) & 0xFF);
							ptr[num26++] = (byte)(stbi__shiftsigned(num28 & num3, shift3, num24) & 0xFF);
							num29 = ((num4 != 0) ? ((uint)stbi__shiftsigned(num28 & num4, shift4, num25)) : 255u);
							num5 |= num29;
							if (num12 == 4)
							{
								ptr[num26++] = (byte)(num29 & 0xFF);
							}
						}
					}
					stbi__skip(s, num11);
				}
			}
			if (num12 == 4 && num5 == 0)
			{
				for (num7 = (int)(4 * s.img_x * s.img_y - 1); num7 >= 0; num7 -= 4)
				{
					ptr[num7] = byte.MaxValue;
				}
			}
			if (num10 != 0)
			{
				byte b2 = 0;
				for (num8 = 0; num8 < (int)s.img_y >> 1; num8++)
				{
					byte* ptr2 = ptr + num8 * s.img_x * num12;
					byte* ptr3 = ptr + (s.img_y - 1 - num8) * s.img_x * num12;
					for (num7 = 0; num7 < (int)s.img_x * num12; num7++)
					{
						b2 = ptr2[num7];
						ptr2[num7] = ptr3[num7];
						ptr3[num7] = b2;
					}
				}
			}
			if (req_comp != 0 && req_comp != num12)
			{
				ptr = stbi__convert_format(ptr, num12, req_comp, s.img_x, s.img_y);
				if (ptr == null)
				{
					return ptr;
				}
			}
			*x = (int)s.img_x;
			*y = (int)s.img_y;
			if (comp != null)
			{
				*comp = s.img_n;
			}
			return ptr;
		}

		public unsafe static int stbi__bmp_info(stbi__context s, int* x, int* y, int* comp)
		{
			stbi__bmp_data stbi__bmp_data = new stbi__bmp_data
			{
				all_a = 255u
			};
			if (stbi__bmp_parse_header(s, &stbi__bmp_data) == null)
			{
				stbi__rewind(s);
				return 0;
			}
			if (x != null)
			{
				*x = (int)s.img_x;
			}
			if (y != null)
			{
				*y = (int)s.img_y;
			}
			if (comp != null)
			{
				if (stbi__bmp_data.bpp == 24 && stbi__bmp_data.ma == 4278190080u)
				{
					*comp = 3;
				}
				else
				{
					*comp = ((stbi__bmp_data.ma != 0) ? 4 : 3);
				}
			}
			return 1;
		}

		public static int stbi__bmp_test_raw(stbi__context s)
		{
			int num = 0;
			if (stbi__get8(s) != 66)
			{
				return 0;
			}
			if (stbi__get8(s) != 77)
			{
				return 0;
			}
			stbi__get32le(s);
			stbi__get16le(s);
			stbi__get16le(s);
			stbi__get32le(s);
			num = (int)stbi__get32le(s);
			if (num != 12 && num != 40 && num != 56 && num != 108 && num != 124)
			{
				return 0;
			}
			return 1;
		}

		public unsafe static int stbi__bmp_set_mask_defaults(stbi__bmp_data* info, int compress)
		{
			switch (compress)
			{
			case 3:
				return 1;
			case 0:
				if (info->bpp == 16)
				{
					info->mr = 31744u;
					info->mg = 992u;
					info->mb = 31u;
				}
				else if (info->bpp == 32)
				{
					info->mr = 16711680u;
					info->mg = 65280u;
					info->mb = 255u;
					info->ma = 4278190080u;
					info->all_a = 0u;
				}
				else
				{
					info->mr = (info->mg = (info->mb = (info->ma = 0u)));
				}
				return 1;
			default:
				return 0;
			}
		}

		public unsafe static void* stbi__bmp_parse_header(stbi__context s, stbi__bmp_data* info)
		{
			int num = 0;
			if (stbi__get8(s) != 66 || stbi__get8(s) != 77)
			{
				return (void*)(int)((stbi__err("not BMP") != 0) ? 0u : 0u);
			}
			stbi__get32le(s);
			stbi__get16le(s);
			stbi__get16le(s);
			info->offset = (int)stbi__get32le(s);
			num = (info->hsz = (int)stbi__get32le(s));
			info->mr = (info->mg = (info->mb = (info->ma = 0u)));
			info->extra_read = 14;
			if (info->offset < 0)
			{
				return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
			}
			if (num != 12 && num != 40 && num != 56 && num != 108 && num != 124)
			{
				return (void*)(int)((stbi__err("unknown BMP") != 0) ? 0u : 0u);
			}
			if (num == 12)
			{
				s.img_x = (uint)stbi__get16le(s);
				s.img_y = (uint)stbi__get16le(s);
			}
			else
			{
				s.img_x = stbi__get32le(s);
				s.img_y = stbi__get32le(s);
			}
			if (stbi__get16le(s) != 1)
			{
				return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
			}
			info->bpp = stbi__get16le(s);
			if (num != 12)
			{
				int num2 = (int)stbi__get32le(s);
				if (num2 == 1 || num2 == 2)
				{
					return (void*)(int)((stbi__err("BMP RLE") != 0) ? 0u : 0u);
				}
				if (num2 >= 4)
				{
					return (void*)(int)((stbi__err("BMP JPEG/PNG") != 0) ? 0u : 0u);
				}
				if (num2 == 3 && info->bpp != 16 && info->bpp != 32)
				{
					return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
				}
				stbi__get32le(s);
				stbi__get32le(s);
				stbi__get32le(s);
				stbi__get32le(s);
				stbi__get32le(s);
				if (num == 40 || num == 56)
				{
					if (num == 56)
					{
						stbi__get32le(s);
						stbi__get32le(s);
						stbi__get32le(s);
						stbi__get32le(s);
					}
					if (info->bpp == 16 || info->bpp == 32)
					{
						switch (num2)
						{
						case 0:
							stbi__bmp_set_mask_defaults(info, num2);
							break;
						case 3:
							info->mr = stbi__get32le(s);
							info->mg = stbi__get32le(s);
							info->mb = stbi__get32le(s);
							info->extra_read += 12;
							if (info->mr == info->mg && info->mg == info->mb)
							{
								return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
							}
							break;
						default:
							return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
						}
					}
				}
				else
				{
					int num3 = 0;
					if (num != 108 && num != 124)
					{
						return (void*)(int)((stbi__err("bad BMP") != 0) ? 0u : 0u);
					}
					info->mr = stbi__get32le(s);
					info->mg = stbi__get32le(s);
					info->mb = stbi__get32le(s);
					info->ma = stbi__get32le(s);
					if (num2 != 3)
					{
						stbi__bmp_set_mask_defaults(info, num2);
					}
					stbi__get32le(s);
					for (num3 = 0; num3 < 12; num3++)
					{
						stbi__get32le(s);
					}
					if (num == 124)
					{
						stbi__get32le(s);
						stbi__get32le(s);
						stbi__get32le(s);
						stbi__get32le(s);
					}
				}
			}
			return (void*)1;
		}

		public static void stbi_hdr_to_ldr_gamma(float gamma)
		{
			stbi__h2l_gamma_i = 1f / gamma;
		}

		public static void stbi_hdr_to_ldr_scale(float scale)
		{
			stbi__h2l_scale_i = 1f / scale;
		}

		public static void stbi_ldr_to_hdr_gamma(float gamma)
		{
			stbi__l2h_gamma = gamma;
		}

		public static void stbi_ldr_to_hdr_scale(float scale)
		{
			stbi__l2h_scale = scale;
		}

		public static void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
		{
			stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
		}

		public static void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
		{
			stbi__de_iphone_flag_global = flag_true_if_should_convert;
		}

		public static void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
		{
			stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
		}

		public static void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
		{
			stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
			stbi__unpremultiply_on_load_set = 1;
		}

		public static void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert)
		{
			stbi__de_iphone_flag_local = flag_true_if_should_convert;
			stbi__de_iphone_flag_set = 1;
		}

		public static void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
		{
			stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
			stbi__vertically_flip_on_load_set = 1;
		}

		public unsafe static void* stbi__malloc(ulong size)
		{
			return CRuntime.malloc(size);
		}

		public static int stbi__addsizes_valid(int a, int b)
		{
			if (b < 0)
			{
				return 0;
			}
			return (a <= int.MaxValue - b) ? 1 : 0;
		}

		public static int stbi__mul2sizes_valid(int a, int b)
		{
			if (a < 0 || b < 0)
			{
				return 0;
			}
			if (b == 0)
			{
				return 1;
			}
			return (a <= int.MaxValue / b) ? 1 : 0;
		}

		public static int stbi__mad2sizes_valid(int a, int b, int add)
		{
			if (stbi__mul2sizes_valid(a, b) == 0 || stbi__addsizes_valid(a * b, add) == 0)
			{
				return 0;
			}
			return 1;
		}

		public static int stbi__mad3sizes_valid(int a, int b, int c, int add)
		{
			if (stbi__mul2sizes_valid(a, b) == 0 || stbi__mul2sizes_valid(a * b, c) == 0 || stbi__addsizes_valid(a * b * c, add) == 0)
			{
				return 0;
			}
			return 1;
		}

		public static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
		{
			if (stbi__mul2sizes_valid(a, b) == 0 || stbi__mul2sizes_valid(a * b, c) == 0 || stbi__mul2sizes_valid(a * b * c, d) == 0 || stbi__addsizes_valid(a * b * c * d, add) == 0)
			{
				return 0;
			}
			return 1;
		}

		public unsafe static void* stbi__malloc_mad2(int a, int b, int add)
		{
			if (stbi__mad2sizes_valid(a, b, add) == 0)
			{
				return null;
			}
			return stbi__malloc((ulong)(a * b + add));
		}

		public unsafe static void* stbi__malloc_mad3(int a, int b, int c, int add)
		{
			if (stbi__mad3sizes_valid(a, b, c, add) == 0)
			{
				return null;
			}
			return stbi__malloc((ulong)(a * b * c + add));
		}

		public unsafe static void* stbi__malloc_mad4(int a, int b, int c, int d, int add)
		{
			if (stbi__mad4sizes_valid(a, b, c, d, add) == 0)
			{
				return null;
			}
			return stbi__malloc((ulong)(a * b * c * d + add));
		}

		public static int stbi__addints_valid(int a, int b)
		{
			if (a >= 0 != b >= 0)
			{
				return 1;
			}
			if (a < 0 && b < 0)
			{
				return (a >= int.MinValue - b) ? 1 : 0;
			}
			return (a <= int.MaxValue - b) ? 1 : 0;
		}

		public static int stbi__mul2shorts_valid(int a, int b)
		{
			if (b == 0 || b == -1)
			{
				return 1;
			}
			if (a >= 0 == b >= 0)
			{
				return (a <= 32767 / b) ? 1 : 0;
			}
			if (b < 0)
			{
				return (a <= -32768 / b) ? 1 : 0;
			}
			return (a >= -32768 / b) ? 1 : 0;
		}

		public unsafe static float* stbi__ldr_to_hdr(byte* data, int x, int y, int comp)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			if (data == null)
			{
				return null;
			}
			float* ptr = (float*)stbi__malloc_mad4(x, y, comp, 4, 0);
			if (ptr == null)
			{
				CRuntime.free(data);
				return (float*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			num3 = (((comp & 1) == 0) ? (comp - 1) : comp);
			for (num = 0; num < x * y; num++)
			{
				for (num2 = 0; num2 < num3; num2++)
				{
					ptr[num * comp + num2] = (float)(CRuntime.pow((float)(int)data[num * comp + num2] / 255f, stbi__l2h_gamma) * (double)stbi__l2h_scale);
				}
			}
			if (num3 < comp)
			{
				for (num = 0; num < x * y; num++)
				{
					ptr[num * comp + num3] = (float)(int)data[num * comp + num3] / 255f;
				}
			}
			CRuntime.free(data);
			return ptr;
		}

		public unsafe static void* stbi__load_main(stbi__context s, int* x, int* y, int* comp, int req_comp, stbi__result_info* ri, int bpc)
		{
			CRuntime.memset(ri, 0, (ulong)sizeof(stbi__result_info));
			ri->bits_per_channel = 8;
			ri->channel_order = 0;
			ri->num_channels = 0;
			if (stbi__png_test(s) != 0)
			{
				return stbi__png_load(s, x, y, comp, req_comp, ri);
			}
			if (stbi__bmp_test(s) != 0)
			{
				return stbi__bmp_load(s, x, y, comp, req_comp, ri);
			}
			if (stbi__gif_test(s) != 0)
			{
				return stbi__gif_load(s, x, y, comp, req_comp, ri);
			}
			if (stbi__psd_test(s) != 0)
			{
				return stbi__psd_load(s, x, y, comp, req_comp, ri, bpc);
			}
			if (stbi__jpeg_test(s) != 0)
			{
				return stbi__jpeg_load(s, x, y, comp, req_comp, ri);
			}
			if (stbi__hdr_test(s) != 0)
			{
				return stbi__hdr_to_ldr(stbi__hdr_load(s, x, y, comp, req_comp, ri), *x, *y, (req_comp != 0) ? req_comp : (*comp));
			}
			if (stbi__tga_test(s) != 0)
			{
				return stbi__tga_load(s, x, y, comp, req_comp, ri);
			}
			return (void*)(int)((stbi__err("unknown image type") != 0) ? 0u : 0u);
		}

		public unsafe static byte* stbi__convert_16_to_8(ushort* orig, int w, int h, int channels)
		{
			int num = 0;
			int num2 = w * h * channels;
			byte* ptr = (byte*)stbi__malloc((ulong)num2);
			if (ptr == null)
			{
				return (byte*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			for (num = 0; num < num2; num++)
			{
				ptr[num] = (byte)((orig[num] >> 8) & 0xFF);
			}
			CRuntime.free(orig);
			return ptr;
		}

		public unsafe static ushort* stbi__convert_8_to_16(byte* orig, int w, int h, int channels)
		{
			int num = 0;
			int num2 = w * h * channels;
			ushort* ptr = (ushort*)stbi__malloc((ulong)(num2 * 2));
			if (ptr == null)
			{
				return (ushort*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			for (num = 0; num < num2; num++)
			{
				ptr[num] = (ushort)((orig[num] << 8) + orig[num]);
			}
			CRuntime.free(orig);
			return ptr;
		}

		public unsafe static void stbi__vertical_flip(void* image, int w, int h, int bytes_per_pixel)
		{
			int num = 0;
			int num2 = w * bytes_per_pixel;
			byte* ptr = stackalloc byte[2048];
			for (num = 0; num < h >> 1; num++)
			{
				byte* ptr2 = (byte*)image + num * num2;
				byte* ptr3 = (byte*)image + (h - num - 1) * num2;
				ulong num3 = (ulong)num2;
				while (num3 != 0L)
				{
					ulong num4 = ((num3 < 2048) ? num3 : 2048);
					CRuntime.memcpy(ptr, ptr2, num4);
					CRuntime.memcpy(ptr2, ptr3, num4);
					CRuntime.memcpy(ptr3, ptr, num4);
					ptr2 += num4;
					ptr3 += num4;
					num3 -= num4;
				}
			}
		}

		public unsafe static void stbi__vertical_flip_slices(void* image, int w, int h, int z, int bytes_per_pixel)
		{
			int num = 0;
			int num2 = w * h * bytes_per_pixel;
			byte* ptr = (byte*)image;
			for (num = 0; num < z; num++)
			{
				stbi__vertical_flip(ptr, w, h, bytes_per_pixel);
				ptr += num2;
			}
		}

		public unsafe static byte* stbi__load_and_postprocess_8bit(stbi__context s, int* x, int* y, int* comp, int req_comp)
		{
			stbi__result_info stbi__result_info = default(stbi__result_info);
			void* ptr = stbi__load_main(s, x, y, comp, req_comp, &stbi__result_info, 8);
			if (ptr == null)
			{
				return null;
			}
			if (stbi__result_info.bits_per_channel != 8)
			{
				ptr = stbi__convert_16_to_8((ushort*)ptr, *x, *y, (req_comp == 0) ? (*comp) : req_comp);
				stbi__result_info.bits_per_channel = 8;
			}
			if (((stbi__vertically_flip_on_load_set != 0) ? stbi__vertically_flip_on_load_local : stbi__vertically_flip_on_load_global) != 0)
			{
				int bytes_per_pixel = ((req_comp != 0) ? req_comp : (*comp));
				stbi__vertical_flip(ptr, *x, *y, bytes_per_pixel);
			}
			return (byte*)ptr;
		}

		public unsafe static ushort* stbi__load_and_postprocess_16bit(stbi__context s, int* x, int* y, int* comp, int req_comp)
		{
			stbi__result_info stbi__result_info = default(stbi__result_info);
			void* ptr = stbi__load_main(s, x, y, comp, req_comp, &stbi__result_info, 16);
			if (ptr == null)
			{
				return null;
			}
			if (stbi__result_info.bits_per_channel != 16)
			{
				ptr = stbi__convert_8_to_16((byte*)ptr, *x, *y, (req_comp == 0) ? (*comp) : req_comp);
				stbi__result_info.bits_per_channel = 16;
			}
			if (((stbi__vertically_flip_on_load_set != 0) ? stbi__vertically_flip_on_load_local : stbi__vertically_flip_on_load_global) != 0)
			{
				int num = ((req_comp != 0) ? req_comp : (*comp));
				stbi__vertical_flip(ptr, *x, *y, num * 2);
			}
			return (ushort*)ptr;
		}

		public unsafe static void stbi__float_postprocess(float* result, int* x, int* y, int* comp, int req_comp)
		{
			if (((stbi__vertically_flip_on_load_set != 0) ? stbi__vertically_flip_on_load_local : stbi__vertically_flip_on_load_global) != 0 && result != null)
			{
				int num = ((req_comp != 0) ? req_comp : (*comp));
				stbi__vertical_flip(result, *x, *y, num * 4);
			}
		}

		public unsafe static float* stbi__loadf_main(stbi__context s, int* x, int* y, int* comp, int req_comp)
		{
			if (stbi__hdr_test(s) != 0)
			{
				stbi__result_info stbi__result_info = default(stbi__result_info);
				float* ptr = stbi__hdr_load(s, x, y, comp, req_comp, &stbi__result_info);
				if (ptr != null)
				{
					stbi__float_postprocess(ptr, x, y, comp, req_comp);
				}
				return ptr;
			}
			byte* ptr2 = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
			if (ptr2 != null)
			{
				return stbi__ldr_to_hdr(ptr2, *x, *y, (req_comp != 0) ? req_comp : (*comp));
			}
			return (float*)(int)((stbi__err("unknown image type") != 0) ? 0u : 0u);
		}

		public static int stbi__get16be(stbi__context s)
		{
			return (stbi__get8(s) << 8) + stbi__get8(s);
		}

		public static uint stbi__get32be(stbi__context s)
		{
			return (uint)((uint)(stbi__get16be(s) << 16) + stbi__get16be(s));
		}

		public static int stbi__get16le(stbi__context s)
		{
			return stbi__get8(s) + (stbi__get8(s) << 8);
		}

		public static uint stbi__get32le(stbi__context s)
		{
			return (uint)(stbi__get16le(s) + (stbi__get16le(s) << 16));
		}

		public static byte stbi__compute_y(int r, int g, int b)
		{
			return (byte)(r * 77 + g * 150 + 29 * b >> 8);
		}

		public unsafe static byte* stbi__convert_format(byte* data, int img_n, int req_comp, uint x, uint y)
		{
			int num = 0;
			int num2 = 0;
			if (req_comp == img_n)
			{
				return data;
			}
			byte* ptr = (byte*)stbi__malloc_mad3(req_comp, (int)x, (int)y, 0);
			if (ptr == null)
			{
				CRuntime.free(data);
				return (byte*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			for (num2 = 0; num2 < (int)y; num2++)
			{
				byte* ptr2 = data + num2 * x * img_n;
				byte* ptr3 = ptr + num2 * x * req_comp;
				switch (img_n * 8 + req_comp)
				{
				case 10:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = byte.MaxValue;
						num--;
						ptr2++;
						ptr3 += 2;
					}
					break;
				case 11:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						num--;
						ptr2++;
						ptr3 += 3;
					}
					break;
				case 12:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						ptr3[3] = byte.MaxValue;
						num--;
						ptr2++;
						ptr3 += 4;
					}
					break;
				case 17:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						num--;
						ptr2 += 2;
						ptr3++;
					}
					break;
				case 19:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						num--;
						ptr2 += 2;
						ptr3 += 3;
					}
					break;
				case 20:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						ptr3[3] = ptr2[1];
						num--;
						ptr2 += 2;
						ptr3 += 4;
					}
					break;
				case 28:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = ptr2[1];
						ptr3[2] = ptr2[2];
						ptr3[3] = byte.MaxValue;
						num--;
						ptr2 += 3;
						ptr3 += 4;
					}
					break;
				case 25:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y(*ptr2, ptr2[1], ptr2[2]);
						num--;
						ptr2 += 3;
						ptr3++;
					}
					break;
				case 26:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y(*ptr2, ptr2[1], ptr2[2]);
						ptr3[1] = byte.MaxValue;
						num--;
						ptr2 += 3;
						ptr3 += 2;
					}
					break;
				case 33:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y(*ptr2, ptr2[1], ptr2[2]);
						num--;
						ptr2 += 4;
						ptr3++;
					}
					break;
				case 34:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y(*ptr2, ptr2[1], ptr2[2]);
						ptr3[1] = ptr2[3];
						num--;
						ptr2 += 4;
						ptr3 += 2;
					}
					break;
				case 35:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = ptr2[1];
						ptr3[2] = ptr2[2];
						num--;
						ptr2 += 4;
						ptr3 += 3;
					}
					break;
				default:
					CRuntime.free(data);
					CRuntime.free(ptr);
					return (byte*)(int)((stbi__err("unsupported") != 0) ? 0u : 0u);
				}
			}
			CRuntime.free(data);
			return ptr;
		}

		public static ushort stbi__compute_y_16(int r, int g, int b)
		{
			return (ushort)(r * 77 + g * 150 + 29 * b >> 8);
		}

		public unsafe static ushort* stbi__convert_format16(ushort* data, int img_n, int req_comp, uint x, uint y)
		{
			int num = 0;
			int num2 = 0;
			if (req_comp == img_n)
			{
				return data;
			}
			ushort* ptr = (ushort*)stbi__malloc((ulong)(req_comp * x * y * 2));
			if (ptr == null)
			{
				CRuntime.free(data);
				return (ushort*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			for (num2 = 0; num2 < (int)y; num2++)
			{
				ushort* ptr2 = data + num2 * x * img_n;
				ushort* ptr3 = ptr + num2 * x * req_comp;
				switch (img_n * 8 + req_comp)
				{
				case 10:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = ushort.MaxValue;
						num--;
						ptr2++;
						ptr3 += 2;
					}
					break;
				case 11:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						num--;
						ptr2++;
						ptr3 += 3;
					}
					break;
				case 12:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						ptr3[3] = ushort.MaxValue;
						num--;
						ptr2++;
						ptr3 += 4;
					}
					break;
				case 17:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						num--;
						ptr2 += 2;
						ptr3++;
					}
					break;
				case 19:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						num--;
						ptr2 += 2;
						ptr3 += 3;
					}
					break;
				case 20:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = (ptr3[1] = (ptr3[2] = *ptr2));
						ptr3[3] = ptr2[1];
						num--;
						ptr2 += 2;
						ptr3 += 4;
					}
					break;
				case 28:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = ptr2[1];
						ptr3[2] = ptr2[2];
						ptr3[3] = ushort.MaxValue;
						num--;
						ptr2 += 3;
						ptr3 += 4;
					}
					break;
				case 25:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y_16(*ptr2, ptr2[1], ptr2[2]);
						num--;
						ptr2 += 3;
						ptr3++;
					}
					break;
				case 26:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y_16(*ptr2, ptr2[1], ptr2[2]);
						ptr3[1] = ushort.MaxValue;
						num--;
						ptr2 += 3;
						ptr3 += 2;
					}
					break;
				case 33:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y_16(*ptr2, ptr2[1], ptr2[2]);
						num--;
						ptr2 += 4;
						ptr3++;
					}
					break;
				case 34:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = stbi__compute_y_16(*ptr2, ptr2[1], ptr2[2]);
						ptr3[1] = ptr2[3];
						num--;
						ptr2 += 4;
						ptr3 += 2;
					}
					break;
				case 35:
					num = (int)(x - 1);
					while (num >= 0)
					{
						*ptr3 = *ptr2;
						ptr3[1] = ptr2[1];
						ptr3[2] = ptr2[2];
						num--;
						ptr2 += 4;
						ptr3 += 3;
					}
					break;
				default:
					CRuntime.free(data);
					CRuntime.free(ptr);
					return (ushort*)(int)((stbi__err("unsupported") != 0) ? 0u : 0u);
				}
			}
			CRuntime.free(data);
			return ptr;
		}

		public static byte stbi__clamp(int x)
		{
			if ((uint)x > 255u)
			{
				if (x < 0)
				{
					return 0;
				}
				if (x > 255)
				{
					return byte.MaxValue;
				}
			}
			return (byte)x;
		}

		public static byte stbi__blinn_8x8(byte x, byte y)
		{
			int num = x * y + 128;
			return (byte)((uint)(num + (num >>> 8)) >> 8);
		}

		public static int stbi__bitreverse16(int n)
		{
			n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
			n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
			n = ((n & 0xF0F0) >> 4) | ((n & 0xF0F) << 4);
			n = ((n & 0xFF00) >> 8) | ((n & 0xFF) << 8);
			return n;
		}

		public static int stbi__bit_reverse(int v, int bits)
		{
			return stbi__bitreverse16(v) >> 16 - bits;
		}

		public static int stbi__high_bit(uint z)
		{
			int num = 0;
			if (z == 0)
			{
				return -1;
			}
			if (z >= 65536)
			{
				num += 16;
				z >>= 16;
			}
			if (z >= 256)
			{
				num += 8;
				z >>= 8;
			}
			if (z >= 16)
			{
				num += 4;
				z >>= 4;
			}
			if (z >= 4)
			{
				num += 2;
				z >>= 2;
			}
			if (z >= 2)
			{
				num++;
			}
			return num;
		}

		public static int stbi__bitcount(uint a)
		{
			a = (a & 0x55555555) + ((a >> 1) & 0x55555555);
			a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
			a = (a + (a >> 4)) & 0xF0F0F0F;
			a += a >> 8;
			a += a >> 16;
			return (int)(a & 0xFF);
		}

		public static int stbi__shiftsigned(uint v, int shift, int bits)
		{
			v = ((shift >= 0) ? (v >> shift) : (v << -shift));
			v >>= 8 - bits;
			return (int)(v * stbi__shiftsigned_mul_table[bits]) >> stbi__shiftsigned_shift_table[bits];
		}

		public unsafe static int stbi__info_main(stbi__context s, int* x, int* y, int* comp)
		{
			if (stbi__jpeg_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__png_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__gif_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__bmp_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__psd_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__hdr_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			if (stbi__tga_info(s, x, y, comp) != 0)
			{
				return 1;
			}
			return stbi__err("unknown image type");
		}

		public static int stbi__is_16_main(stbi__context s)
		{
			if (stbi__png_is16(s) != 0)
			{
				return 1;
			}
			if (stbi__psd_is16(s) != 0)
			{
				return 1;
			}
			return 0;
		}

		public static int stbi__gif_test(stbi__context s)
		{
			int result = stbi__gif_test_raw(s);
			stbi__rewind(s);
			return result;
		}

		public unsafe static void* stbi__gif_load(stbi__context s, int* x, int* y, int* comp, int req_comp, stbi__result_info* ri)
		{
			byte* ptr = null;
			stbi__gif stbi__gif = new stbi__gif();
			ptr = stbi__gif_load_next(s, stbi__gif, comp, req_comp, null);
			if (ptr != null)
			{
				*x = stbi__gif.w;
				*y = stbi__gif.h;
				if (req_comp != 0 && req_comp != 4)
				{
					ptr = stbi__convert_format(ptr, 4, req_comp, (uint)stbi__gif.w, (uint)stbi__gif.h);
				}
			}
			else if (stbi__gif._out_ != null)
			{
				CRuntime.free(stbi__gif._out_);
			}
			CRuntime.free(stbi__gif.history);
			CRuntime.free(stbi__gif.background);
			return ptr;
		}

		public unsafe static void* stbi__load_gif_main(stbi__context s, int** delays, int* x, int* y, int* z, int* comp, int req_comp)
		{
			if (stbi__gif_test(s) != 0)
			{
				int num = 0;
				byte* ptr = null;
				byte* ptr2 = null;
				byte* two_back = null;
				stbi__gif stbi__gif = new stbi__gif();
				int num2 = 0;
				if (delays != null)
				{
					*delays = null;
				}
				do
				{
					ptr = stbi__gif_load_next(s, stbi__gif, comp, req_comp, two_back);
					if (ptr == null)
					{
						continue;
					}
					*x = stbi__gif.w;
					*y = stbi__gif.h;
					num++;
					num2 = stbi__gif.w * stbi__gif.h * 4;
					if (ptr2 != null)
					{
						void* ptr3 = CRuntime.realloc(ptr2, (ulong)(num * num2));
						if (ptr3 == null)
						{
							return stbi__load_gif_main_outofmem(stbi__gif, ptr2, delays);
						}
						ptr2 = (byte*)ptr3;
						if (delays != null)
						{
							int* ptr4 = (int*)CRuntime.realloc(*delays, (ulong)(4 * num));
							if (ptr4 == null)
							{
								return stbi__load_gif_main_outofmem(stbi__gif, ptr2, delays);
							}
							*delays = ptr4;
						}
					}
					else
					{
						ptr2 = (byte*)stbi__malloc((ulong)(num * num2));
						if (ptr2 == null)
						{
							return stbi__load_gif_main_outofmem(stbi__gif, ptr2, delays);
						}
						if (delays != null)
						{
							*delays = (int*)stbi__malloc((ulong)(num * 4));
							if (*delays == null)
							{
								return stbi__load_gif_main_outofmem(stbi__gif, ptr2, delays);
							}
						}
					}
					CRuntime.memcpy(ptr2 + (num - 1) * num2, ptr, (ulong)num2);
					if (num >= 2)
					{
						two_back = ptr2 - 2 * num2;
					}
					if (delays != null)
					{
						(*delays)[(long)num - 1L] = stbi__gif.delay;
					}
				}
				while (ptr != null);
				CRuntime.free(stbi__gif._out_);
				CRuntime.free(stbi__gif.history);
				CRuntime.free(stbi__gif.background);
				if (req_comp != 0 && req_comp != 4)
				{
					ptr2 = stbi__convert_format(ptr2, 4, req_comp, (uint)(num * stbi__gif.w), (uint)stbi__gif.h);
				}
				*z = num;
				return ptr2;
			}
			return (void*)(int)((stbi__err("not GIF") != 0) ? 0u : 0u);
		}

		public unsafe static int stbi__gif_info(stbi__context s, int* x, int* y, int* comp)
		{
			return stbi__gif_info_raw(s, x, y, comp);
		}

		public static int stbi__gif_test_raw(stbi__context s)
		{
			int num = 0;
			if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
			{
				return 0;
			}
			num = stbi__get8(s);
			if (num != 57 && num != 55)
			{
				return 0;
			}
			if (stbi__get8(s) != 97)
			{
				return 0;
			}
			return 1;
		}

		public static void stbi__gif_parse_colortable(stbi__context s, byte[][] pal, int num_entries, int transp)
		{
			int num = 0;
			for (num = 0; num < num_entries; num++)
			{
				pal[num][2] = stbi__get8(s);
				pal[num][1] = stbi__get8(s);
				pal[num][0] = stbi__get8(s);
				pal[num][3] = (byte)((transp != num) ? 255u : 0u);
			}
		}

		public unsafe static int stbi__gif_header(stbi__context s, stbi__gif g, int* comp, int is_info)
		{
			byte b = 0;
			if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
			{
				return stbi__err("not GIF");
			}
			b = stbi__get8(s);
			if (b != 55 && b != 57)
			{
				return stbi__err("not GIF");
			}
			if (stbi__get8(s) != 97)
			{
				return stbi__err("not GIF");
			}
			stbi__g_failure_reason = "";
			g.w = stbi__get16le(s);
			g.h = stbi__get16le(s);
			g.flags = stbi__get8(s);
			g.bgindex = stbi__get8(s);
			g.ratio = stbi__get8(s);
			g.transparent = -1;
			if (g.w > 16777216)
			{
				return stbi__err("too large");
			}
			if (g.h > 16777216)
			{
				return stbi__err("too large");
			}
			if (comp != null)
			{
				*comp = 4;
			}
			if (is_info != 0)
			{
				return 1;
			}
			if ((g.flags & 0x80) != 0)
			{
				stbi__gif_parse_colortable(s, g.pal, 2 << (g.flags & 7), -1);
			}
			return 1;
		}

		public unsafe static int stbi__gif_info_raw(stbi__context s, int* x, int* y, int* comp)
		{
			stbi__gif stbi__gif = new stbi__gif();
			if (stbi__gif == null)
			{
				return stbi__err("outofmem");
			}
			if (stbi__gif_header(s, stbi__gif, comp, 1) == 0)
			{
				stbi__rewind(s);
				return 0;
			}
			if (x != null)
			{
				*x = stbi__gif.w;
			}
			if (y != null)
			{
				*y = stbi__gif.h;
			}
			return 1;
		}

		public unsafe static void stbi__out_gif_code(stbi__gif g, ushort code)
		{
			int num = 0;
			if (g.codes[code].prefix >= 0)
			{
				stbi__out_gif_code(g, (ushort)g.codes[code].prefix);
			}
			if (g.cur_y >= g.max_y)
			{
				return;
			}
			num = g.cur_x + g.cur_y;
			byte* ptr = g._out_ + num;
			g.history[num / 4] = 1;
			byte[] array = g.color_table[g.codes[code].suffix];
			if (array[3] > 128)
			{
				*ptr = array[2];
				ptr[1] = array[1];
				ptr[2] = array[0];
				ptr[3] = array[3];
			}
			g.cur_x += 4;
			if (g.cur_x >= g.max_x)
			{
				g.cur_x = g.start_x;
				g.cur_y += g.step;
				while (g.cur_y >= g.max_y && g.parse > 0)
				{
					g.step = (1 << g.parse) * g.line_size;
					g.cur_y = g.start_y + (g.step >> 1);
					g.parse--;
				}
			}
		}

		public unsafe static byte* stbi__process_gif_raster(stbi__context s, stbi__gif g)
		{
			byte b = 0;
			int num = 0;
			int num2 = 0;
			uint num3 = 0u;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = 0;
			int num10 = 0;
			b = stbi__get8(s);
			if (b > 12)
			{
				return null;
			}
			num10 = 1 << (int)b;
			num3 = 1u;
			num4 = b + 1;
			num5 = (1 << num4) - 1;
			num8 = 0;
			num9 = 0;
			for (num2 = 0; num2 < num10; num2++)
			{
				g.codes[num2].prefix = -1;
				g.codes[num2].first = (byte)num2;
				g.codes[num2].suffix = (byte)num2;
			}
			num6 = num10 + 2;
			num7 = -1;
			num = 0;
			while (true)
			{
				if (num9 < num4)
				{
					if (num == 0)
					{
						num = stbi__get8(s);
						if (num == 0)
						{
							return g._out_;
						}
					}
					num--;
					num8 |= stbi__get8(s) << num9;
					num9 += 8;
					continue;
				}
				int num11 = num8 & num5;
				num8 >>= num4;
				num9 -= num4;
				if (num11 == num10)
				{
					num4 = b + 1;
					num5 = (1 << num4) - 1;
					num6 = num10 + 2;
					num7 = -1;
					num3 = 0u;
					continue;
				}
				if (num11 == num10 + 1)
				{
					stbi__skip(s, num);
					while ((num = stbi__get8(s)) > 0)
					{
						stbi__skip(s, num);
					}
					return g._out_;
				}
				if (num11 > num6)
				{
					break;
				}
				if (num3 != 0)
				{
					return (byte*)(int)((stbi__err("no clear code") != 0) ? 0u : 0u);
				}
				if (num7 >= 0)
				{
					fixed (stbi__gif_lzw* ptr = &g.codes[num6++])
					{
						if (num6 > 8192)
						{
							return (byte*)(int)((stbi__err("too many codes") != 0) ? 0u : 0u);
						}
						ptr->prefix = (short)num7;
						ptr->first = g.codes[num7].first;
						ptr->suffix = ((num11 == num6) ? ptr->first : g.codes[num11].first);
					}
				}
				else if (num11 == num6)
				{
					return (byte*)(int)((stbi__err("illegal code in raster") != 0) ? 0u : 0u);
				}
				stbi__out_gif_code(g, (ushort)num11);
				if ((num6 & num5) == 0 && num6 <= 4095)
				{
					num4++;
					num5 = (1 << num4) - 1;
				}
				num7 = num11;
			}
			return (byte*)(int)((stbi__err("illegal code in raster") != 0) ? 0u : 0u);
		}

		public unsafe static byte* stbi__gif_load_next(stbi__context s, stbi__gif g, int* comp, int req_comp, byte* two_back)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			num2 = 0;
			if (g._out_ == null)
			{
				if (stbi__gif_header(s, g, comp, 0) == 0)
				{
					return null;
				}
				if (stbi__mad3sizes_valid(4, g.w, g.h, 0) == 0)
				{
					return (byte*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
				}
				num4 = g.w * g.h;
				g._out_ = (byte*)stbi__malloc((ulong)(4 * num4));
				g.background = (byte*)stbi__malloc((ulong)(4 * num4));
				g.history = (byte*)stbi__malloc((ulong)num4);
				if (g._out_ == null || g.background == null || g.history == null)
				{
					return (byte*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
				}
				CRuntime.memset(g._out_, 0, (ulong)(4 * num4));
				CRuntime.memset(g.background, 0, (ulong)(4 * num4));
				CRuntime.memset(g.history, 0, (ulong)num4);
				num2 = 1;
			}
			else
			{
				num = (g.eflags & 0x1C) >> 2;
				num4 = g.w * g.h;
				if (num == 3 && two_back == null)
				{
					num = 2;
				}
				switch (num)
				{
				case 3:
					for (num3 = 0; num3 < num4; num3++)
					{
						if (g.history[num3] != 0)
						{
							CRuntime.memcpy(g._out_ + num3 * 4, two_back + num3 * 4, 4uL);
						}
					}
					break;
				case 2:
					for (num3 = 0; num3 < num4; num3++)
					{
						if (g.history[num3] != 0)
						{
							CRuntime.memcpy(g._out_ + num3 * 4, g.background + num3 * 4, 4uL);
						}
					}
					break;
				}
				CRuntime.memcpy(g.background, g._out_, (ulong)(4 * g.w * g.h));
			}
			CRuntime.memset(g.history, 0, (ulong)(g.w * g.h));
			while (true)
			{
				switch (stbi__get8(s))
				{
				case 44:
				{
					int num6 = 0;
					int num7 = 0;
					int num8 = 0;
					int num9 = 0;
					num6 = stbi__get16le(s);
					num7 = stbi__get16le(s);
					num8 = stbi__get16le(s);
					num9 = stbi__get16le(s);
					if (num6 + num8 > g.w || num7 + num9 > g.h)
					{
						return (byte*)(int)((stbi__err("bad Image Descriptor") != 0) ? 0u : 0u);
					}
					g.line_size = g.w * 4;
					g.start_x = num6 * 4;
					g.start_y = num7 * g.line_size;
					g.max_x = g.start_x + num8 * 4;
					g.max_y = g.start_y + num9 * g.line_size;
					g.cur_x = g.start_x;
					g.cur_y = g.start_y;
					if (num8 == 0)
					{
						g.cur_y = g.max_y;
					}
					g.lflags = stbi__get8(s);
					if ((g.lflags & 0x40) != 0)
					{
						g.step = 8 * g.line_size;
						g.parse = 3;
					}
					else
					{
						g.step = g.line_size;
						g.parse = 0;
					}
					if ((g.lflags & 0x80) != 0)
					{
						stbi__gif_parse_colortable(s, g.lpal, 2 << (g.lflags & 7), ((g.eflags & 1) != 0) ? g.transparent : (-1));
						g.color_table = g.lpal;
					}
					else
					{
						if ((g.flags & 0x80) == 0)
						{
							return (byte*)(int)((stbi__err("missing color table") != 0) ? 0u : 0u);
						}
						g.color_table = g.pal;
					}
					byte* ptr = stbi__process_gif_raster(s, g);
					if (ptr == null)
					{
						return null;
					}
					num4 = g.w * g.h;
					if (num2 != 0 && g.bgindex > 0)
					{
						for (num3 = 0; num3 < num4; num3++)
						{
							if (g.history[num3] == 0)
							{
								g.pal[g.bgindex][3] = byte.MaxValue;
								fixed (byte* b = &g.pal[g.bgindex][0])
								{
									CRuntime.memcpy(g._out_ + num3 * 4, b, 4uL);
								}
							}
						}
					}
					return ptr;
				}
				case 33:
				{
					int num5 = 0;
					if (stbi__get8(s) == 249)
					{
						num5 = stbi__get8(s);
						if (num5 != 4)
						{
							stbi__skip(s, num5);
							break;
						}
						g.eflags = stbi__get8(s);
						g.delay = 10 * stbi__get16le(s);
						if (g.transparent >= 0)
						{
							g.pal[g.transparent][3] = byte.MaxValue;
						}
						if ((g.eflags & 1) != 0)
						{
							g.transparent = stbi__get8(s);
							if (g.transparent >= 0)
							{
								g.pal[g.transparent][3] = 0;
							}
						}
						else
						{
							stbi__skip(s, 1);
							g.transparent = -1;
						}
					}
					while ((num5 = stbi__get8(s)) != 0)
					{
						stbi__skip(s, num5);
					}
					break;
				}
				case 59:
					return null;
				default:
					return (byte*)(int)((stbi__err("unknown code") != 0) ? 0u : 0u);
				}
			}
		}

		public unsafe static void* stbi__load_gif_main_outofmem(stbi__gif g, byte* _out_, int** delays)
		{
			CRuntime.free(g._out_);
			CRuntime.free(g.history);
			CRuntime.free(g.background);
			if (_out_ != null)
			{
				CRuntime.free(_out_);
			}
			if (delays != null && *delays != null)
			{
				CRuntime.free(*delays);
			}
			return (void*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
		}

		public static int stbi__hdr_test(stbi__context s)
		{
			int num = stbi__hdr_test_core(s, "#?RADIANCE\n");
			stbi__rewind(s);
			if (num == 0)
			{
				num = stbi__hdr_test_core(s, "#?RGBE\n");
				stbi__rewind(s);
			}
			return num;
		}

		public unsafe static float* stbi__hdr_load(stbi__context s, int* x, int* y, int* comp, int req_comp, stbi__result_info* ri)
		{
			byte* ptr = stackalloc byte[4];
			sbyte* buffer = stackalloc sbyte[1024];
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			byte b = 0;
			byte b2 = 0;
			int i = 0;
			int j = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			sbyte* src = stbi__hdr_gettoken(s, buffer);
			if (CRuntime.strcmp(src, "#?RADIANCE") != 0 && CRuntime.strcmp(src, "#?RGBE") != 0)
			{
				return (float*)(int)((stbi__err("not HDR") != 0) ? 0u : 0u);
			}
			sbyte* ptr2;
			while (true)
			{
				ptr2 = stbi__hdr_gettoken(s, buffer);
				if (*ptr2 == 0)
				{
					break;
				}
				if (CRuntime.strcmp(ptr2, "FORMAT=32-bit_rle_rgbe") == 0)
				{
					num = 1;
				}
			}
			if (num == 0)
			{
				return (float*)(int)((stbi__err("unsupported format") != 0) ? 0u : 0u);
			}
			ptr2 = stbi__hdr_gettoken(s, buffer);
			if (CRuntime.strncmp(ptr2, "-Y ", 3uL) != 0)
			{
				return (float*)(int)((stbi__err("unsupported data layout") != 0) ? 0u : 0u);
			}
			ptr2 += 3;
			num3 = (int)CRuntime.strtol(ptr2, &ptr2, 10);
			for (; *ptr2 == 32; ptr2++)
			{
			}
			if (CRuntime.strncmp(ptr2, "+X ", 3uL) != 0)
			{
				return (float*)(int)((stbi__err("unsupported data layout") != 0) ? 0u : 0u);
			}
			ptr2 += 3;
			num2 = (int)CRuntime.strtol(ptr2, null, 10);
			if (num3 > 16777216)
			{
				return (float*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			if (num2 > 16777216)
			{
				return (float*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			*x = num2;
			*y = num3;
			if (comp != null)
			{
				*comp = 3;
			}
			if (req_comp == 0)
			{
				req_comp = 3;
			}
			if (stbi__mad4sizes_valid(num2, num3, req_comp, 4, 0) == 0)
			{
				return (float*)(int)((stbi__err("too large") != 0) ? 0u : 0u);
			}
			float* ptr3 = (float*)stbi__malloc_mad4(num2, num3, req_comp, 4, 0);
			if (ptr3 == null)
			{
				return (float*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			if (num2 < 8 || num2 >= 32768)
			{
				for (; j < num3; j++)
				{
					for (; i < num2; i++)
					{
						stbi__getn(s, ptr, 4);
						stbi__hdr_convert(ptr3 + j * num2 * req_comp + i * req_comp, ptr, req_comp);
					}
				}
			}
			else
			{
				byte* ptr4 = null;
				j = 0;
				while (true)
				{
					if (j < num3)
					{
						num6 = stbi__get8(s);
						num7 = stbi__get8(s);
						num4 = stbi__get8(s);
						if (num6 != 2 || num7 != 2 || (num4 & 0x80) != 0)
						{
							*ptr = (byte)num6;
							ptr[1] = (byte)num7;
							ptr[2] = (byte)num4;
							ptr[3] = stbi__get8(s);
							stbi__hdr_convert(ptr3, ptr, req_comp);
							CRuntime.free(ptr4);
							j = 0;
							for (i = 1; i < num2; i++)
							{
								stbi__getn(s, ptr, 4);
								stbi__hdr_convert(ptr3 + j * num2 * req_comp + i * req_comp, ptr, req_comp);
							}
							for (j = 1; j < num3; j++)
							{
								for (i = 0; i < num2; i++)
								{
									stbi__getn(s, ptr, 4);
									stbi__hdr_convert(ptr3 + j * num2 * req_comp + i * req_comp, ptr, req_comp);
								}
							}
							break;
						}
						num4 <<= 8;
						num4 |= stbi__get8(s);
						if (num4 != num2)
						{
							CRuntime.free(ptr3);
							CRuntime.free(ptr4);
							return (float*)(int)((stbi__err("invalid decoded scanline length") != 0) ? 0u : 0u);
						}
						if (ptr4 == null)
						{
							ptr4 = (byte*)stbi__malloc_mad2(num2, 4, 0);
							if (ptr4 == null)
							{
								CRuntime.free(ptr3);
								return (float*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
							}
						}
						for (num5 = 0; num5 < 4; num5++)
						{
							int num9 = 0;
							i = 0;
							while ((num9 = num2 - i) > 0)
							{
								b = stbi__get8(s);
								if (b > 128)
								{
									b2 = stbi__get8(s);
									b -= 128;
									if (b == 0 || b > num9)
									{
										CRuntime.free(ptr3);
										CRuntime.free(ptr4);
										return (float*)(int)((stbi__err("corrupt") != 0) ? 0u : 0u);
									}
									for (num8 = 0; num8 < b; num8++)
									{
										ptr4[i++ * 4 + num5] = b2;
									}
								}
								else
								{
									if (b == 0 || b > num9)
									{
										CRuntime.free(ptr3);
										CRuntime.free(ptr4);
										return (float*)(int)((stbi__err("corrupt") != 0) ? 0u : 0u);
									}
									for (num8 = 0; num8 < b; num8++)
									{
										ptr4[i++ * 4 + num5] = stbi__get8(s);
									}
								}
							}
						}
						for (i = 0; i < num2; i++)
						{
							stbi__hdr_convert(ptr3 + (j * num2 + i) * req_comp, ptr4 + i * 4, req_comp);
						}
						j++;
						continue;
					}
					if (ptr4 != null)
					{
						CRuntime.free(ptr4);
					}
					break;
				}
			}
			return ptr3;
		}

		public unsafe static int stbi__hdr_info(stbi__context s, int* x, int* y, int* comp)
		{
			sbyte* buffer = stackalloc sbyte[1024];
			int num = 0;
			int num2 = 0;
			if (x == null)
			{
				x = &num2;
			}
			if (y == null)
			{
				y = &num2;
			}
			if (comp == null)
			{
				comp = &num2;
			}
			if (stbi__hdr_test(s) == 0)
			{
				stbi__rewind(s);
				return 0;
			}
			sbyte* ptr;
			while (true)
			{
				ptr = stbi__hdr_gettoken(s, buffer);
				if (*ptr == 0)
				{
					break;
				}
				if (CRuntime.strcmp(ptr, "FORMAT=32-bit_rle_rgbe") == 0)
				{
					num = 1;
				}
			}
			if (num == 0)
			{
				stbi__rewind(s);
				return 0;
			}
			ptr = stbi__hdr_gettoken(s, buffer);
			if (CRuntime.strncmp(ptr, "-Y ", 3uL) != 0)
			{
				stbi__rewind(s);
				return 0;
			}
			ptr += 3;
			*y = (int)CRuntime.strtol(ptr, &ptr, 10);
			for (; *ptr == 32; ptr++)
			{
			}
			if (CRuntime.strncmp(ptr, "+X ", 3uL) != 0)
			{
				stbi__rewind(s);
				return 0;
			}
			ptr += 3;
			*x = (int)CRuntime.strtol(ptr, null, 10);
			*comp = 3;
			return 1;
		}

		public unsafe static byte* stbi__hdr_to_ldr(float* data, int x, int y, int comp)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			if (data == null)
			{
				return null;
			}
			byte* ptr = (byte*)stbi__malloc_mad3(x, y, comp, 0);
			if (ptr == null)
			{
				CRuntime.free(data);
				return (byte*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			num3 = (((comp & 1) == 0) ? (comp - 1) : comp);
			for (num = 0; num < x * y; num++)
			{
				for (num2 = 0; num2 < num3; num2++)
				{
					float num4 = (float)CRuntime.pow(data[num * comp + num2] * stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255f + 0.5f;
					if (num4 < 0f)
					{
						num4 = 0f;
					}
					if (num4 > 255f)
					{
						num4 = 255f;
					}
					ptr[num * comp + num2] = (byte)(int)num4;
				}
				if (num2 < comp)
				{
					float num5 = data[num * comp + num2] * 255f + 0.5f;
					if (num5 < 0f)
					{
						num5 = 0f;
					}
					if (num5 > 255f)
					{
						num5 = 255f;
					}
					ptr[num * comp + num2] = (byte)(int)num5;
				}
			}
			CRuntime.free(data);
			return ptr;
		}

		public static int stbi__hdr_test_core(stbi__context s, string signature)
		{
			int num = 0;
			for (num = 0; num < signature.Length; num++)
			{
				if (stbi__get8(s) != signature[num])
				{
					return 0;
				}
			}
			stbi__rewind(s);
			return 1;
		}

		public unsafe static sbyte* stbi__hdr_gettoken(stbi__context z, sbyte* buffer)
		{
			int num = 0;
			sbyte b = 0;
			b = (sbyte)stbi__get8(z);
			while (stbi__at_eof(z) == 0 && b != 10)
			{
				buffer[num++] = b;
				if (num == 1023)
				{
					while (stbi__at_eof(z) == 0 && stbi__get8(z) != 10)
					{
					}
					break;
				}
				b = (sbyte)stbi__get8(z);
			}
			buffer[num] = 0;
			return buffer;
		}

		public unsafe static void stbi__hdr_convert(float* output, byte* input, int req_comp)
		{
			if (input[3] != 0)
			{
				float num = 0f;
				num = (float)CRuntime.ldexp(1.0, input[3] - 136);
				if (req_comp <= 2)
				{
					*output = (float)(*input + input[1] + input[2]) * num / 3f;
				}
				else
				{
					*output = (float)(int)(*input) * num;
					output[1] = (float)(int)input[1] * num;
					output[2] = (float)(int)input[2] * num;
				}
				if (req_comp == 2)
				{
					output[1] = 1f;
				}
				if (req_comp == 4)
				{
					output[3] = 1f;
				}
			}
			else if ((uint)(req_comp - 1) > 1u)
			{
				switch (req_comp)
				{
				case 4:
					output[3] = 1f;
					break;
				case 3:
					break;
				default:
					return;
				}
				*output = (output[1] = (output[2] = 0f));
			}
			else
			{
				if (req_comp == 2)
				{
					output[1] = 1f;
				}
				*output = 0f;
			}
		}

		public static int stbi__jpeg_test(stbi__context s)
		{
			stbi__jpeg stbi__jpeg = new stbi__jpeg();
			if (stbi__jpeg == null)
			{
				return stbi__err("outofmem");
			}
			stbi__jpeg.s = s;
			stbi__setup_jpeg(stbi__jpeg);
			int result = stbi__decode_jpeg_header(stbi__jpeg, 1);
			stbi__rewind(s);
			return result;
		}

		public unsafe static void* stbi__jpeg_load(stbi__context s, int* x, int* y, int* comp, int req_comp, stbi__result_info* ri)
		{
			stbi__jpeg stbi__jpeg = new stbi__jpeg();
			if (stbi__jpeg == null)
			{
				return (void*)(int)((stbi__err("outofmem") != 0) ? 0u : 0u);
			}
			stbi__jpeg.s = s;
			stbi__setup_jpeg(stbi__jpeg);
			return load_jpeg_image(stbi__jpeg, x, y, comp, req_comp);
		}

		public unsafe static int stbi__jpeg_info(stbi__context s, int* x, int* y, int* comp)
		{
			stbi__jpeg stbi__jpeg = new stbi__jpeg();
			if (stbi__jpeg == null)
			{
				return stbi__err("outofmem");
			}
			stbi__jpeg.s = s;
			return stbi__jpeg_info_raw(stbi__jpeg, x, y, comp);
		}

		public unsafe static int stbi__build_huffman(stbi__huffman* h, int* count)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			uint num4 = 0u;
			for (num = 0; num < 16; num++)
			{
				for (num2 = 0; num2 < count[num]; num2++)
				{
					h->size[num3++] = (byte)(num + 1);
					if (num3 >= 257)
					{
						return stbi__err("bad size list");
					}
				}
			}
			h->size[num3] = 0;
			num4 = 0u;
			num3 = 0;
			for (num2 = 1; num2 <= 16; num2++)
			{
				h->delta[num2] = (int)(num3 - num4);
				if (h->size[num3] == num2)
				{
					while (h->size[num3] == num2)
					{
						h->code[num3++] = (ushort)num4++;
					}
					if (num4 - 1 >= (uint)(1 << num2))
					{
						return stbi__err("bad code lengths");
					}
				}
				h->maxcode[num2] = num4 << 16 - num2;
				num4 <<= 1;
			}
			h->maxcode[num2] = uint.MaxValue;
			CRuntime.memset(h->fast, 255, 512uL);
			for (num = 0; num < num3; num++)
			{
				int num5 = h->size[num];
				if (num5 <= 9)
				{
					int num6 = h->code[num] << 9 - num5;
					int num7 = 1 << 9 - num5;
					for (num2 = 0; num2 < num7; num2++)
					{
						h->fast[num6 + num2] = (byte)num;
					}
				}
			}
			return 1;
		}

		public unsafe static void stbi__build_fast_ac(short[] fast_ac, stbi__huffman* h)
		{
			int num = 0;
			for (num = 0; num < 512; num++)
			{
				byte b = h->fast[num];
				fast_ac[num] = 0;
				if (b >= byte.MaxValue)
				{
					continue;
				}
				byte num2 = h->values[(int)b];
				int num3 = (num2 >> 4) & 0xF;
				int num4 = num2 & 0xF;
				int num5 = h->size[(int)b];
				if (num4 != 0 && num5 + num4 <= 9)
				{
					int num6 = ((num << num5) & 0x1FF) >> 9 - num4;
					int num7 = 1 << num4 - 1;
					if (num6 < num7)
					{
						num6 += (-1 << num4) + 1;
					}
					if (num6 >= -128 && num6 <= 127)
					{
						fast_ac[num] = (short)(num6 * 256 + num3 * 16 + num5 + num4);
					}
				}
			}
		}

		public static void stbi__grow_buffer_unsafe(stbi__jpeg j)
		{
			do
			{
				uint num = (uint)((j.nomore == 0) ? stbi__get8(j.s) : 0);
				if (num == 255)
				{
					int num2 = stbi__get8(j.s);
					while (true)
					{
						switch (num2)
						{
						case 255:
							goto IL_002d;
						default:
							j.marker = (byte)num2;
							j.nomore = 1;
							return;
						case 0:
							break;
						}
						break;
						IL_002d:
						num2 = stbi__get8(j.s);
					}
				}
				j.code_buffer |= num << 24 - j.code_bits;
				j.code_bits += 8;
			}
			while (j.code_bits <= 24);
		}

		public unsafe static int stbi__jpeg_huff_decode(stbi__jpeg j, stbi__huffman* h)
		{
			uint num = 0u;
			int num2 = 0;
			int num3 = 0;
			if (j.code_bits < 16)
			{
				stbi__grow_buffer_unsafe(j);
			}
			num2 = (int)((j.code_buffer >> 23) & 0x1FF);
			num3 = h->fast[num2];
			if (num3 < 255)
			{
				int num4 = h->size[num3];
				if (num4 > j.code_bits)
				{
					return -1;
				}
				j.code_buffer <<= num4;
				j.code_bits -= num4;
				return h->values[num3];
			}
			num = j.code_buffer >> 16;
			for (num3 = 10; num >= h->maxcode[num3]; num3++)
			{
			}
			if (num3 == 17)
			{
				j.code_bits -= 16;
				return -1;
			}
			if (num3 > j.code_bits)
			{
				return -1;
			}
			num2 = (int)(((j.code_buffer >> 32 - num3) & stbi__bmask[num3]) + h->delta[num3]);
			if (num2 < 0 || num2 >= 256)
			{
				return -1;
			}
			j.code_bits -= num3;
			j.code_buffer <<= num3;
			return h->values[num2];
		}

		public static int stbi__extend_receive(stbi__jpeg j, int n)
		{
			uint num = 0u;
			int num2 = 0;
			if (j.code_bits < n)
			{
				stbi__grow_buffer_unsafe(j);
			}
			if (j.code_bits < n)
			{
				return 0;
			}
			num2 = (int)(j.code_buffer >> 31);
			num = CRuntime._lrotl(j.code_buffer, n);
			j.code_buffer = num & ~stbi__bmask[n];
			num &= stbi__bmask[n];
			j.code_bits -= n;
			return (int)(num + (stbi__jbias[n] & (num2 - 1)));
		}

		public static int stbi__jpeg_get_bits(stbi__jpeg j, int n)
		{
			uint num = 0u;
			if (j.code_bits < n)
			{
				stbi__grow_buffer_unsafe(j);
			}
			if (j.code_bits < n)
			{
				return 0;
			}
			num = CRuntime._lrotl(j.code_buffer, n);
			j.code_buffer = num & ~stbi__bmask[n];
			num &= stbi__bmask[n];
			j.code_bits -= n;
			return (int)num;
		}

		public static int stbi__jpeg_get_bit(stbi__jpeg j)
		{
			if (j.code_bits < 1)
			{
				stbi__grow_buffer_unsafe(j);
			}
			if (j.code_bits < 1)
			{
				return 0;
			}
			uint code_buffer = j.code_buffer;
			j.code_buffer <<= 1;
			j.code_bits--;
			return (int)code_buffer & int.MinValue;
		}

		public unsafe static int stbi__jpeg_decode_block(stbi__jpeg j, short* data, stbi__huffman* hdc, stbi__huffman* hac, short[] fac, int b, ushort[] dequant)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			if (j.code_bits < 16)
			{
				stbi__grow_buffer_unsafe(j);
			}
			num4 = stbi__jpeg_huff_decode(j, hdc);
			if (num4 < 0 || num4 > 15)
			{
				return stbi__err("bad huffman code");
			}
			CRuntime.memset(data, 0, 128uL);
			num = ((num4 != 0) ? stbi__extend_receive(j, num4) : 0);
			if (stbi__addints_valid(j.img_comp[b].dc_pred, num) == 0)
			{
				return stbi__err("bad delta");
			}
			num2 = j.img_comp[b].dc_pred + num;
			j.img_comp[b].dc_pred = num2;
			if (stbi__mul2shorts_valid(num2, dequant[0]) == 0)
			{
				return stbi__err("can't merge dc and ac");
			}
			*data = (short)(num2 * dequant[0]);
			num3 = 1;
			do
			{
				uint num5 = 0u;
				int num6 = 0;
				int num7 = 0;
				int num8 = 0;
				if (j.code_bits < 16)
				{
					stbi__grow_buffer_unsafe(j);
				}
				num6 = (int)((j.code_buffer >> 23) & 0x1FF);
				num7 = fac[num6];
				if (num7 != 0)
				{
					num3 += (num7 >> 4) & 0xF;
					num8 = num7 & 0xF;
					if (num8 > j.code_bits)
					{
						return stbi__err("bad huffman code");
					}
					j.code_buffer <<= num8;
					j.code_bits -= num8;
					num5 = stbi__jpeg_dezigzag[num3++];
					data[num5] = (short)((num7 >> 8) * dequant[num5]);
					continue;
				}
				int num9 = stbi__jpeg_huff_decode(j, hac);
				if (num9 < 0)
				{
					return stbi__err("bad huffman code");
				}
				num8 = num9 & 0xF;
				num7 = num9 >> 4;
				if (num8 == 0)
				{
					if (num9 != 240)
					{
						break;
					}
					num3 += 16;
				}
				else
				{
					num3 += num7;
					num5 = stbi__jpeg_dezigzag[num3++];
					data[num5] = (short)(stbi__extend_receive(j, num8) * dequant[num5]);
				}
			}
			while (num3 < 64);
			return 1;
		}

		public unsafe static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg j, short* data, stbi__huffman* hdc, int b)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			if (j.spec_end != 0)
			{
				return stbi__err("can't merge dc and ac");
			}
			if (j.code_bits < 16)
			{
				stbi__grow_buffer_unsafe(j);
			}
			if (j.succ_high == 0)
			{
				CRuntime.memset(data, 0, 128uL);
				num3 = stbi__jpeg_huff_decode(j, hdc);
				int num4;
				switch (num3)
				{
				default:
					return stbi__err("can't merge dc and ac");
				case 0:
					num4 = 0;
					break;
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
				case 8:
				case 9:
				case 10:
				case 11:
				case 12:
				case 13:
				case 14:
				case 15:
					num4 = stbi__extend_receive(j, num3);
					break;
				}
				num = num4;
				if (stbi__addints_valid(j.img_comp[b].dc_pred, num) == 0)
				{
					return stbi__err("bad delta");
				}
				num2 = j.img_comp[b].dc_pred + num;
				j.img_comp[b].dc_pred = num2;
				if (stbi__mul2shorts_valid(num2, 1 << j.succ_low) == 0)
				{
					return stbi__err("can't merge dc and ac");
				}
				*data = (short)(num2 * (1 << j.succ_low));
			}
			else if (stbi__jpeg_get_bit(j) != 0)
			{
				*data += (short)(1 << j.succ_low);
			}
			return 1;
		}

		public unsafe static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg j, short* data, stbi__huffman* hac, short[] fac)
		{
			int num = 0;
			if (j.spec_start == 0)
			{
				return stbi__err("can't merge dc and ac");
			}
			if (j.succ_high == 0)
			{
				int succ_low = j.succ_low;
				if (j.eob_run != 0)
				{
					j.eob_run--;
					return 1;
				}
				num = j.spec_start;
				do
				{
					uint num2 = 0u;
					int num3 = 0;
					int num4 = 0;
					int num5 = 0;
					if (j.code_bits < 16)
					{
						stbi__grow_buffer_unsafe(j);
					}
					num3 = (int)((j.code_buffer >> 23) & 0x1FF);
					num4 = fac[num3];
					if (num4 != 0)
					{
						num += (num4 >> 4) & 0xF;
						num5 = num4 & 0xF;
						if (num5 > j.code_bits)
						{
							return stbi__err("bad huffman code");
						}
						j.code_buffer <<= num5;
						j.code_bits -= num5;
						num2 = stbi__jpeg_dezigzag[num++];
						data[num2] = (short)((num4 >> 8) * (1 << succ_low));
						continue;
					}
					int num6 = stbi__jpeg_huff_decode(j, hac);
					if (num6 < 0)
					{
						return stbi__err("bad huffman code");
					}
					num5 = num6 & 0xF;
					num4 = num6 >> 4;
					if (num5 == 0)
					{
						if (num4 < 15)
						{
							j.eob_run = 1 << num4;
							if (num4 != 0)
							{
								j.eob_run += stbi__jpeg_get_bits(j, num4);
							}
							j.eob_run--;
							break;
						}
						num += 16;
					}
					else
					{
						num += num4;
						num2 = stbi__jpeg_dezigzag[num++];
						data[num2] = (short)(stbi__extend_receive(j, num5) * (1 << succ_low));
					}
				}
				while (num <= j.spec_end);
			}
			else
			{
				short num7 = (short)(1 << j.succ_low);
				if (j.eob_run != 0)
				{
					j.eob_run--;
					for (num = j.spec_start; num <= j.spec_end; num++)
					{
						short* ptr = data + (int)stbi__jpeg_dezigzag[num];
						if (*ptr != 0 && stbi__jpeg_get_bit(j) != 0 && (*ptr & num7) == 0)
						{
							if (*ptr > 0)
							{
								*ptr += num7;
							}
							else
							{
								*ptr -= num7;
							}
						}
					}
				}
				else
				{
					num = j.spec_start;
					do
					{
						int num8 = 0;
						int num9 = 0;
						int num10 = stbi__jpeg_huff_decode(j, hac);
						if (num10 < 0)
						{
							return stbi__err("bad huffman code");
						}
						num9 = num10 & 0xF;
						num8 = num10 >> 4;
						switch (num9)
						{
						case 0:
							if (num8 < 15)
							{
								j.eob_run = (1 << num8) - 1;
								if (num8 != 0)
								{
									j.eob_run += stbi__jpeg_get_bits(j, num8);
								}
								num8 = 64;
							}
							break;
						default:
							return stbi__err("bad huffman code");
						case 1:
							num9 = ((stbi__jpeg_get_bit(j) == 0) ? (-num7) : num7);
							break;
						}
						while (num <= j.spec_end)
						{
							short* ptr2 = data + (int)stbi__jpeg_dezigzag[num++];
							if (*ptr2 != 0)
							{
								if (stbi__jpeg_get_bit(j) != 0 && (*ptr2 & num7) == 0)
								{
									if (*ptr2 > 0)
									{
										*ptr2 += num7;
									}
									else
									{
										*ptr2 -= num7;
									}
								}
							}
							else
							{
								if (num8 == 0)
								{
									*ptr2 = (short)num9;
									break;
								}
								num8--;
							}
						}
					}
					while (num <= j.spec_end);
				}
			}
			return 1;
		}

		public unsafe static void stbi__idct_block(byte* _out_, int out_stride, short* data)
		{
			int num = 0;
			int* ptr = stackalloc int[64];
			int* ptr2 = ptr;
			short* ptr3 = data;
			num = 0;
			while (num < 8)
			{
				if (ptr3[8] == 0 && ptr3[16] == 0 && ptr3[24] == 0 && ptr3[32] == 0 && ptr3[40] == 0 && ptr3[48] == 0 && ptr3[56] == 0)
				{
					int num2 = *ptr3 * 4;
					*ptr2 = (ptr2[8] = (ptr2[16] = (ptr2[24] = (ptr2[32] = (ptr2[40] = (ptr2[48] = (ptr2[56] = num2)))))));
				}
				else
				{
					int num3 = 0;
					int num4 = 0;
					int num5 = 0;
					int num6 = 0;
					int num7 = 0;
					int num8 = 0;
					int num9 = 0;
					int num10 = 0;
					int num11 = 0;
					int num12 = 0;
					int num13 = 0;
					int num14 = 0;
					num8 = ptr3[16];
					num9 = ptr3[48];
					num7 = (num8 + num9) * 2217;
					num5 = num7 + num9 * -7567;
					num6 = num7 + num8 * 3135;
					num8 = *ptr3;
					num9 = ptr3[32];
					num3 = (num8 + num9) * 4096;
					num4 = (num8 - num9) * 4096;
					num11 = num3 + num6;
					num14 = num3 - num6;
					num12 = num4 + num5;
					num13 = num4 - num5;
					num3 = ptr3[56];
					num4 = ptr3[40];
					num5 = ptr3[24];
					num6 = ptr3[8];
					num9 = num3 + num5;
					num10 = num4 + num6;
					num7 = num3 + num6;
					num8 = num4 + num5;
					int num15 = (num9 + num10) * 4816;
					num3 *= 1223;
					num4 *= 8410;
					num5 *= 12586;
					num6 *= 6149;
					num7 = num15 + num7 * -3685;
					num8 = num15 + num8 * -10497;
					num9 *= -8034;
					num10 *= -1597;
					num6 += num7 + num10;
					num5 += num8 + num9;
					num4 += num8 + num10;
					num3 += num7 + num9;
					num11 += 512;
					num12 += 512;
					num13 += 512;
					num14 += 512;
					*ptr2 = num11 + num6 >> 10;
					ptr2[56] = num11 - num6 >> 10;
					ptr2[8] = num12 + num5 >> 10;
					ptr2[48] = num12 - num5 >> 10;
					ptr2[16] = num13 + num4 >> 10;
					ptr2[40] = num13 - num4 >> 10;
					ptr2[24] = num14 + num3 >> 10;
					ptr2[32] = num14 - num3 >> 10;
				}
				num++;
				ptr3++;
				ptr2++;
			}
			num = 0;
			ptr2 = ptr;
			byte* ptr4 = _out_;
			while (num < 8)
			{
				int num16 = 0;
				int num17 = 0;
				int num18 = 0;
				int num19 = 0;
				int num20 = 0;
				int num21 = 0;
				int num22 = 0;
				int num23 = 0;
				int num24 = 0;
				int num25 = 0;
				int num26 = 0;
				int num27 = 0;
				num21 = ptr2[2];
				num22 = ptr2[6];
				num20 = (num21 + num22) * 2217;
				num18 = num20 + num22 * -7567;
				num19 = num20 + num21 * 3135;
				num21 = *ptr2;
				num22 = ptr2[4];
				num16 = (num21 + num22) * 4096;
				num17 = (num21 - num22) * 4096;
				num24 = num16 + num19;
				num27 = num16 - num19;
				num25 = num17 + num18;
				num26 = num17 - num18;
				num16 = ptr2[7];
				num17 = ptr2[5];
				num18 = ptr2[3];
				num19 = ptr2[1];
				num22 = num16 + num18;
				num23 = num17 + num19;
				num20 = num16 + num19;
				num21 = num17 + num18;
				int num28 = (num22 + num23) * 4816;
				num16 *= 1223;
				num17 *= 8410;
				num18 *= 12586;
				num19 *= 6149;
				num20 = num28 + num20 * -3685;
				num21 = num28 + num21 * -10497;
				num22 *= -8034;
				num23 *= -1597;
				num19 += num20 + num23;
				num18 += num21 + num22;
				num17 += num21 + num23;
				num16 += num20 + num22;
				num24 += 16842752;
				num25 += 16842752;
				num26 += 16842752;
				num27 += 16842752;
				*ptr4 = stbi__clamp(num24 + num19 >> 17);
				ptr4[7] = stbi__clamp(num24 - num19 >> 17);
				ptr4[1] = stbi__clamp(num25 + num18 >> 17);
				ptr4[6] = stbi__clamp(num25 - num18 >> 17);
				ptr4[2] = stbi__clamp(num26 + num17 >> 17);
				ptr4[5] = stbi__clamp(num26 - num17 >> 17);
				ptr4[3] = stbi__clamp(num27 + num16 >> 17);
				ptr4[4] = stbi__clamp(num27 - num16 >> 17);
				num++;
				ptr2 += 8;
				ptr4 += out_stride;
			}
		}

		public static byte stbi__get_marker(stbi__jpeg j)
		{
			byte b = 0;
			if (j.marker != byte.MaxValue)
			{
				b = j.marker;
				j.marker = byte.MaxValue;
				return b;
			}
			b = stbi__get8(j.s);
			if (b != byte.MaxValue)
			{
				return byte.MaxValue;
			}
			while (b == byte.MaxValue)
			{
				b = stbi__get8(j.s);
			}
			return b;
		}

		public static void stbi__jpeg_reset(stbi__jpeg j)
		{
			j.code_bits = 0;
			j.code_buffer = 0u;
			j.nomore = 0;
			j.img_comp[0].dc_pred = (j.img_comp[1].dc_pred = (j.img_comp[2].dc_pred = (j.img_comp[3].dc_pred = 0)));
			j.marker = byte.MaxValue;
			j.todo = ((j.restart_interval != 0) ? j.restart_interval : int.MaxValue);
			j.eob_run = 0;
		}

		public unsafe static int stbi__parse_entropy_coded_data(stbi__jpeg z)
		{
			stbi__jpeg_reset(z);
			if (z.progressive == 0)
			{
				if (z.scan_n == 1)
				{
					int num = 0;
					int num2 = 0;
					short* ptr = stackalloc short[64];
					int num3 = z.order[0];
					int num4 = z.img_comp[num3].x + 7 >> 3;
					int num5 = z.img_comp[num3].y + 7 >> 3;
					for (num2 = 0; num2 < num5; num2++)
					{
						for (num = 0; num < num4; num++)
						{
							int ha = z.img_comp[num3].ha;
							fixed (stbi__huffman* hdc = &z.huff_dc[z.img_comp[num3].hd])
							{
								fixed (stbi__huffman* hac = &z.huff_ac[ha])
								{
									if (stbi__jpeg_decode_block(z, ptr, hdc, hac, z.fast_ac[ha], num3, z.dequant[z.img_comp[num3].tq]) == 0)
									{
										return 0;
									}
								}
							}
							z.idct_block_kernel(z.img_comp[num3].data + z.img_comp[num3].w2 * num2 * 8 + num * 8, z.img_comp[num3].w2, ptr);
							if (--z.todo <= 0)
							{
								if (z.code_bits < 24)
								{
									stbi__grow_buffer_unsafe(z);
								}
								if (z.marker < 208 || z.marker > 215)
								{
									return 1;
								}
								stbi__jpeg_reset(z);
							}
						}
					}
					return 1;
				}
				int num6 = 0;
				int num7 = 0;
				int num8 = 0;
				int num9 = 0;
				int num10 = 0;
				short* ptr2 = stackalloc short[64];
				for (num7 = 0; num7 < z.img_mcu_y; num7++)
				{
					for (num6 = 0; num6 < z.img_mcu_x; num6++)
					{
						for (num8 = 0; num8 < z.scan_n; num8++)
						{
							int num11 = z.order[num8];
							for (num10 = 0; num10 < z.img_comp[num11].v; num10++)
							{
								for (num9 = 0; num9 < z.img_comp[num11].h; num9++)
								{
									int num12 = (num6 * z.img_comp[num11].h + num9) * 8;
									int num13 = (num7 * z.img_comp[num11].v + num10) * 8;
									int ha2 = z.img_comp[num11].ha;
									fixed (stbi__huffman* hdc2 = &z.huff_dc[z.img_comp[num11].hd])
									{
										fixed (stbi__huffman* hac2 = &z.huff_ac[ha2])
										{
											if (stbi__jpeg_decode_block(z, ptr2, hdc2, hac2, z.fast_ac[ha2], num11, z.dequant[z.img_comp[num11].tq]) == 0)
											{
												return 0;
											}
										}
									}
									z.idct_block_kernel(z.img_comp[num11].data + z.img_comp[num11].w2 * num13 + num12, z.img_comp[num11].w2, ptr2);
								}
							}
						}
						if (--z.todo <= 0)
						{
							if (z.code_bits < 24)
							{
								stbi__grow_buffer_unsafe(z);
							}
							if (z.marker < 208 || z.marker > 215)
							{
								return 1;
							}
							stbi__jpeg_reset(z);
						}
					}
				}
				return 1;
			}
			if (z.scan_n == 1)
			{
				int num14 = 0;
				int num15 = 0;
				int num16 = z.order[0];
				int num17 = z.img_comp[num16].x + 7 >> 3;
				int num18 = z.img_comp[num16].y + 7 >> 3;
				for (num15 = 0; num15 < num18; num15++)
				{
					for (num14 = 0; num14 < num17; num14++)
					{
						short* data = z.img_comp[num16].coeff + 64 * (num14 + num15 * z.img_comp[num16].coeff_w);
						if (z.spec_start == 0)
						{
							fixed (stbi__huffman* hdc3 = &z.huff_dc[z.img_comp[num16].hd])
							{
								if (stbi__jpeg_decode_block_prog_dc(z, data, hdc3, num16) == 0)
								{
									return 0;
								}
							}
						}
						else
						{
							int ha3 = z.img_comp[num16].ha;
							fixed (stbi__huffman* hac3 = &z.huff_ac[ha3])
							{
								if (stbi__jpeg_decode_block_prog_ac(z, data, hac3, z.fast_ac[ha3]) == 0)
								{
									return 0;
								}
							}
						}
						if (--z.todo <= 0)
						{
							if (z.code_bits < 24)
							{
								stbi__grow_buffer_unsafe(z);
							}
							if (z.marker < 208 || z.marker > 215)
							{
								return 1;
							}
							stbi__jpeg_reset(z);
						}
					}
				}
				return 1;
			}
			int num19 = 0;
			int num20 = 0;
			int num21 = 0;
			int num22 = 0;
			int num23 = 0;
			for (num20 = 0; num20 < z.img_mcu_y; num20++)
			{
				for (num19 = 0; num19 < z.img_mcu_x; num19++)
				{
					for (num21 = 0; num21 < z.scan_n; num21++)
					{
						int num24 = z.order[num21];
						for (num23 = 0; num23 < z.img_comp[num24].v; num23++)
						{
							for (num22 = 0; num22 < z.img_comp[num24].h; num22++)
							{
								int num25 = num19 * z.img_comp[num24].h + num22;
								int num26 = num20 * z.img_comp[num24].v + num23;
								short* data2 = z.img_comp[num24].coeff + 64 * (num25 + num26 * z.img_comp[num24].coeff_w);
								fixed (stbi__huffman* hdc4 = &z.huff_dc[z.img_comp[num24].hd])
								{
									if (stbi__jpeg_decode_block_prog_dc(z, data2, hdc4, num24) == 0)
									{
										return 0;
									}
								}
							}
						}
					}
					if (--z.todo <= 0)
					{
						if (z.code_bits < 24)
						{
							stbi__grow_buffer_unsafe(z);
						}
						if (z.marker < 208 || z.marker > 215)
						{
							return 1;
						}
						stbi__jpeg_reset(z);
					}
				}
			}
			return 1;
		}

		public unsafe static void stbi__jpeg_dequantize(short* data, ushort[] dequant)
		{
			int num = 0;
			for (num = 0; num < 64; num++)
			{
				data[num] *= (short)dequant[num];
			}
		}

		public unsafe static void stbi__jpeg_finish(stbi__jpeg z)
		{
			if (z.progressive == 0)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			for (num3 = 0; num3 < z.s.img_n; num3++)
			{
				int num4 = z.img_comp[num3].x + 7 >> 3;
				int num5 = z.img_comp[num3].y + 7 >> 3;
				for (num2 = 0; num2 < num5; num2++)
				{
					for (num = 0; num < num4; num++)
					{
						short* ptr = z.img_comp[num3].coeff + 64 * (num + num2 * z.img_comp[num3].coeff_w);
						stbi__jpeg_dequantize(ptr, z.dequant[z.img_comp[num3].tq]);
						z.idct_block_kernel(z.img_comp[num3].data + z.img_comp[num3].w2 * num2 * 8 + num * 8, z.img_comp[num3].w2, ptr);
					}
				}
			}
		}

		public unsafe static int stbi__process_marker(stbi__jpeg z, int m)
		{
			int num = 0;
			switch (m)
			{
			case 255:
				return stbi__err("expected marker");
			case 221:
				if (stbi__get16be(z.s) != 4)
				{
					return stbi__err("bad DRI len");
				}
				z.restart_interval = stbi__get16be(z.s);
				return 1;
			case 219:
				num = stbi__get16be(z.s) - 2;
				while (num > 0)
				{
					byte num11 = stbi__get8(z.s);
					int num12 = num11 >> 4;
					int num13 = ((num12 != 0) ? 1 : 0);
					int num14 = num11 & 0xF;
					int num15 = 0;
					if (num12 != 0 && num12 != 1)
					{
						return stbi__err("bad DQT type");
					}
					if (num14 > 3)
					{
						return stbi__err("bad DQT table");
					}
					for (num15 = 0; num15 < 64; num15++)
					{
						z.dequant[num14][stbi__jpeg_dezigzag[num15]] = (ushort)((num13 != 0) ? stbi__get16be(z.s) : stbi__get8(z.s));
					}
					num -= ((num13 != 0) ? 129 : 65);
				}
				return (num == 0) ? 1 : 0;
			case 196:
			{
				num = stbi__get16be(z.s) - 2;
				int* ptr = stackalloc int[16];
				while (num > 0)
				{
					int num6 = 0;
					int num7 = 0;
					byte num8 = stbi__get8(z.s);
					int num9 = num8 >> 4;
					int num10 = num8 & 0xF;
					if (num9 > 1 || num10 > 3)
					{
						return stbi__err("bad DHT header");
					}
					for (num6 = 0; num6 < 16; num6++)
					{
						ptr[num6] = stbi__get8(z.s);
						num7 += ptr[num6];
					}
					if (num7 > 256)
					{
						return stbi__err("bad DHT header");
					}
					num -= 17;
					if (num9 == 0)
					{
						fixed (stbi__huffman* ptr2 = &z.huff_dc[num10])
						{
							if (stbi__build_huffman(ptr2, ptr) == 0)
							{
								return 0;
							}
							byte* ptr3 = ptr2->values;
							for (num6 = 0; num6 < num7; num6++)
							{
								ptr3[num6] = stbi__get8(z.s);
							}
						}
					}
					else
					{
						fixed (stbi__huffman* ptr4 = &z.huff_ac[num10])
						{
							if (stbi__build_huffman(ptr4, ptr) == 0)
							{
								return 0;
							}
							byte* ptr5 = ptr4->values;
							for (num6 = 0; num6 < num7; num6++)
							{
								ptr5[num6] = stbi__get8(z.s);
							}
						}
					}
					if (num9 != 0)
					{
						fixed (stbi__huffman* h = &z.huff_ac[num10])
						{
							stbi__build_fast_ac(z.fast_ac[num10], h);
						}
					}
					num -= num7;
				}
				return (num == 0) ? 1 : 0;
			}
			default:
				if ((m >= 224 && m <= 239) || m == 254)
				{
					num = stbi__get16be(z.s);
					if (num < 2)
					{
						if (m == 254)
						{
							return stbi__err("bad COM len");
						}
						return stbi__err("bad APP len");
					}
					num -= 2;
					if (m == 224 && num >= 5)
					{
						int num2 = 1;
						int num3 = 0;
						for (num3 = 0; num3 < 5; num3++)
						{
							if (stbi__get8(z.s) != stbi__process_marker_tag[num3])
							{
								num2 = 0;
							}
						}
						num -= 5;
						if (num2 != 0)
						{
							z.jfif = 1;
						}
					}
					else if (m == 238 && num >= 12)
					{
						int num4 = 1;
						int num5 = 0;
						for (num5 = 0; num5 < 6; num5++)
						{
							if (stbi__get8(z.s) != stbi__process_marker_tag[num5])
							{
								num4 = 0;
							}
						}
						num -= 6;
						if (num4 != 0)
						{
							stbi__get8(z.s);
							stbi__get16be(z.s);
							stbi__get16be(z.s);
							z.app14_color_transform = stbi__get8(z.s);
							num -= 6;
						}
					}
					stbi__skip(z.s, num);
					return 1;
				}
				return stbi__err("unknown marker");
			}
		}

		public static int stbi__process_scan_header(stbi__jpeg z)
		{
			int num = 0;
			int num2 = stbi__get16be(z.s);
			z.scan_n = stbi__get8(z.s);
			if (z.scan_n < 1 || z.scan_n > 4 || z.scan_n > z.s.img_n)
			{
				return stbi__err("bad SOS component count");
			}
			if (num2 != 6 + 2 * z.scan_n)
			{
				return stbi__err("bad SOS len");
			}
			for (num = 0; num < z.scan_n; num++)
			{
				int num3 = stbi__get8(z.s);
				int num4 = 0;
				int num5 = stbi__get8(z.s);
				for (num4 = 0; num4 < z.s.img_n && z.img_comp[num4].id != num3; num4++)
				{
				}
				if (num4 == z.s.img_n)
				{
					return 0;
				}
				z.img_comp[num4].hd = num5 >> 4;
				if (z.img_comp[num4].hd > 3)
				{
					return stbi__err("bad DC huff");
				}
				z.img_comp[num4].ha = num5 & 0xF;
				if (z.img_comp[num4].ha > 3)
				{
					return stbi__err("bad AC huff");
				}
				z.order[num] = num4;
			}
			int num6 = 0;
			z.spec_start = stbi__get8(z.s);
			z.spec_end = stbi__get8(z.s);
			num6 = stbi__get8(z.s);
			z.succ_high = num6 >> 4;
			z.succ_low = num6 & 0xF;
			if (z.progressive != 0)
			{
				if (z.spec_start > 63 || z.spec_end > 63 || z.spec_start > z.spec_end || z.succ_high > 13 || z.succ_low > 13)
				{
					return stbi__err("bad SOS");
				}
			}
			else
			{
				if (z.spec_start != 0)
				{
					return stbi__err("bad SOS");
				}
				if (z.succ_high != 0 || z.succ_low != 0)
				{
					return stbi__err("bad SOS");
				}
				z.spec_end = 63;
			}
			return 1;
		}

		public unsafe static int stbi__free_jpeg_components(stbi__jpeg z, int ncomp, int why)
		{
			int num = 0;
			for (num = 0; num < ncomp; num++)
			{
				if (z.img_comp[num].raw_data != null)
				{
					CRuntime.free(z.img_comp[num].raw_data);
					z.img_comp[num].raw_data = null;
					z.img_comp[num].data = null;
				}
				if (z.img_comp[num].raw_coeff != null)
				{
					CRuntime.free(z.img_comp[num].raw_coeff);
					z.img_comp[num].raw_coeff = null;
					z.img_comp[num].coeff = null;
				}
				if (z.img_comp[num].linebuf != null)
				{
					CRuntime.free(z.img_comp[num].linebuf);
					z.img_comp[num].linebuf = null;
				}
			}
			return why;
		}

		public unsafe static int stbi__process_frame_header(stbi__jpeg z, int scan)
		{
			stbi__context s = z.s;
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 1;
			int num5 = 1;
			int num6 = 0;
			num = stbi__get16be(s);
			if (num < 11)
			{
				return stbi__err("bad SOF len");
			}
			if (stbi__get8(s) != 8)
			{
				return stbi__err("only 8-bit");
			}
			s.img_y = (uint)stbi__get16be(s);
			if (s.img_y == 0)
			{
				return stbi__err("no header height");
			}
			s.img_x = (uint)stbi__get16be(s);
			if (s.img_x == 0)
			{
				return stbi__err("0 width");
			}
			if (s.img_y > 16777216)
			{
				return stbi__err("too large");
			}
			if (s.img_x > 16777216)
			{
				return stbi__err("too large");
			}
			num6 = stbi__get8(s);
			if (num6 != 3 && num6 != 1 && num6 != 4)
			{
				return stbi__err("bad component count");
			}
			s.img_n = num6;
			for (num2 = 0; num2 < num6; num2++)
			{
				z.img_comp[num2].data = null;
				z.img_comp[num2].linebuf = null;
			}
			if (num != 8 + 3 * s.img_n)
			{
				return stbi__err("bad SOF len");
			}
			z.rgb = 0;
			for (num2 = 0; num2 < s.img_n; num2++)
			{
				z.img_comp[num2].id = stbi__get8(s);
				if (s.img_n == 3 && z.img_comp[num2].id == stbi__process_frame_header_rgb[num2])
				{
					z.rgb++;
				}
				num3 = stbi__get8(s);
				z.img_comp[num2].h = num3 >> 4;
				if (z.img_comp[num2].h == 0 || z.img_comp[num2].h > 4)
				{
					return stbi__err("bad H");
				}
				z.img_comp[num2].v = num3 & 0xF;
				if (z.img_comp[num2].v == 0 || z.img_comp[num2].v > 4)
				{
					return stbi__err("bad V");
				}
				z.img_comp[num2].tq = stbi__get8(s);
				if (z.img_comp[num2].tq > 3)