From 2b31232b305698622318dc2186b0900faedb63e5 Mon Sep 17 00:00:00 2001 From: Razmoth <12517189-Razmoth@users.noreply.gitlab.com> Date: Fri, 6 Jan 2023 22:33:59 +0400 Subject: [PATCH] v0.80.30 --- .../AssetStudio.PInvoke.csproj | 8 +- AssetStudio.PInvoke/DllLoader.cs | 24 +- AssetStudio.PInvoke/Utf8StringHandle.cs | 100 - AssetStudio.sln | 59 +- AssetStudio/AssetEntry.cs | 10 +- AssetStudio/AssetGroupOption.cs | 10 + AssetStudio/AssetStudio.csproj | 22 +- AssetStudio/AssetsHelper.cs | 436 ++ AssetStudio/AssetsManager.cs | 295 +- AssetStudio/BlockStream.cs | 59 + AssetStudio/BundleFile.cs | 213 +- AssetStudio/CABManager.cs | 207 - AssetStudio/Classes/Animation.cs | 12 - AssetStudio/Classes/AnimationClip.cs | 675 +-- AssetStudio/Classes/Animator.cs | 28 +- AssetStudio/Classes/AnimatorController.cs | 15 +- .../Classes/AnimatorOverrideController.cs | 21 - AssetStudio/Classes/AssetBundle.cs | 107 +- AssetStudio/Classes/GameObject.cs | 66 +- AssetStudio/Classes/IndexObject.cs | 19 +- AssetStudio/Classes/Material.cs | 96 +- AssetStudio/Classes/Mesh.cs | 91 +- AssetStudio/Classes/MeshRenderer.cs | 3 +- AssetStudio/Classes/MiHoYoBinData.cs | 108 +- AssetStudio/Classes/PPtr.cs | 26 +- AssetStudio/Classes/Renderer.cs | 142 +- .../Classes/RuntimeAnimatorController.cs | 2 - AssetStudio/Classes/Shader.cs | 72 +- AssetStudio/Classes/SkinnedMeshRenderer.cs | 18 +- AssetStudio/Classes/Texture2D.cs | 7 +- AssetStudio/Classes/Transform.cs | 27 - AssetStudio/Classes/VideoClip.cs | 2 +- AssetStudio/{Game => }/Crypto/AES.cs | 0 AssetStudio/Crypto/BlkUtils.cs | 59 + AssetStudio/Crypto/CNUnity.cs | 164 + AssetStudio/Crypto/CryptoHelper.cs | 59 + AssetStudio/{Game => }/Crypto/MT19937_64.cs | 29 +- AssetStudio/Crypto/Mr0kUtils.cs | 72 + AssetStudio/{Game => }/Crypto/XORShift128.cs | 24 +- AssetStudio/CryptoStream.cs | 27 + AssetStudio/EndianBinaryReader.cs | 183 +- AssetStudio/ExportTypeList.cs | 18 + .../Extensions/BinaryReaderExtensions.cs | 192 - .../Extensions/BinaryWriterExtensions.cs | 27 - .../Extensions/BitConverterExtensions.cs | 107 - AssetStudio/Extensions/ByteArrayExtensions.cs | 38 + AssetStudio/Extensions/PrimitiveExtensions.cs | 79 - .../Extensions/StringBuilderExtensions.cs | 87 - AssetStudio/FileReader.cs | 75 +- AssetStudio/FileType.cs | 6 +- AssetStudio/Game/BH3/WMVFile.cs | 30 - AssetStudio/Game/CB1/CB1File.cs | 21 - AssetStudio/Game/CBX/CBXFile.cs | 39 - AssetStudio/Game/Crypto/Blk.cs | 76 - AssetStudio/Game/Crypto/Crypto.cs | 81 - AssetStudio/Game/Crypto/Mark.cs | 66 - AssetStudio/Game/Crypto/Mr0k.cs | 85 - AssetStudio/Game/GI/GIFile.cs | 48 - AssetStudio/Game/GI/Mhy0File.cs | 164 - AssetStudio/Game/GameFile.cs | 140 - AssetStudio/Game/SR_CB3/BlocksFile.cs | 30 - AssetStudio/Game/TOT/TOTFile.cs | 32 - AssetStudio/GameManager.cs | 170 +- AssetStudio/IImported.cs | 34 +- AssetStudio/ILogger.cs | 9 +- AssetStudio/IYAMLExportable.cs | 7 - AssetStudio/ImportHelper.cs | 256 + AssetStudio/Keys.json | 38 + AssetStudio/Logger.cs | 13 +- AssetStudio/Math/Float.cs | 27 - AssetStudio/Math/Quaternion.cs | 13 +- AssetStudio/Math/Vector3.cs | 12 +- AssetStudio/Mhy0File.cs | 197 + AssetStudio/ObjectInfo.cs | 36 +- AssetStudio/ObjectReader.cs | 5 +- AssetStudio/Progress.cs | 15 +- AssetStudio/ResourceIndex.cs | 16 +- AssetStudio/SerializedFile.cs | 26 +- AssetStudio/TypeTreeHelper.cs | 4 +- AssetStudio/UnityCNKeyManager.cs | 68 + AssetStudio/YAML/Base/Emitter.cs | 231 - AssetStudio/YAML/Base/MappingStyle.cs | 18 - AssetStudio/YAML/Base/MetaType.cs | 8 - AssetStudio/YAML/Base/ScalarStyle.cs | 28 - AssetStudio/YAML/Base/ScalarType.cs | 17 - AssetStudio/YAML/Base/SequenceStyle.cs | 51 - AssetStudio/YAML/Base/YAMLDocument.cs | 42 - AssetStudio/YAML/Base/YAMLMappingNode.cs | 330 -- AssetStudio/YAML/Base/YAMLNode.cs | 40 - AssetStudio/YAML/Base/YAMLNodeType.cs | 20 - AssetStudio/YAML/Base/YAMLScalarNode.cs | 456 -- AssetStudio/YAML/Base/YAMLSequenceNode.cs | 213 - AssetStudio/YAML/Base/YAMLTag.cs | 26 - AssetStudio/YAML/Base/YAMLWriter.cs | 98 - .../Utils/Extensions/ArrayYAMLExtensions.cs | 25 - .../Utils/Extensions/EmitterExtensions.cs | 82 - .../IDictionaryExportYAMLExtensions.cs | 143 - .../Extensions/IDictionaryYAMLExtensions.cs | 105 - .../Extensions/IEnumerableYAMLExtensions.cs | 273 - .../Utils/Extensions/IListYAMLExtensions.cs | 171 - .../Extensions/YAMLMappingNodeExtensions.cs | 31 - AssetStudioCLI/App.config | 35 + AssetStudioCLI/AssetStudioCLI.csproj | 19 +- AssetStudioCLI/Exporter.cs | 146 +- AssetStudioCLI/Options.cs | 70 + AssetStudioCLI/Program.cs | 75 +- AssetStudioCLI/Studio.cs | 340 +- .../AssetStudioFBXNative.vcxproj | 1 - AssetStudioFBXNative/resource.h | 2 +- .../AssetStudioFBXWrapper.csproj | 10 +- AssetStudioFBXWrapper/Fbx.PInvoke.cs | 8 +- .../FbxExporterContext.PInvoke.cs | 411 +- AssetStudioFBXWrapper/FbxExporterContext.cs | 44 +- AssetStudioGUI/AssetStudioGUI.csproj | 36 +- AssetStudioGUI/AssetStudioGUIForm.Designer.cs | 408 +- AssetStudioGUI/AssetStudioGUIForm.cs | 635 ++- AssetStudioGUI/AssetStudioGUIForm.resx | 62 +- AssetStudioGUI/CNUnityForm.Designer.cs | 123 + AssetStudioGUI/CNUnityForm.cs | 83 + AssetStudioGUI/CNUnityForm.resx | 66 + AssetStudioGUI/Components/OpenFolderDialog.cs | 20 +- AssetStudioGUI/ExportOptions.Designer.cs | 324 +- AssetStudioGUI/ExportOptions.cs | 33 +- AssetStudioGUI/ExportOptions.resx | 71 +- AssetStudioGUI/Exporter.cs | 71 +- AssetStudioGUI/GUILogger.cs | 5 +- AssetStudioGUI/Program.cs | 2 - .../Properties/Settings.Designer.cs | 707 ++- AssetStudioGUI/Properties/Settings.settings | 26 +- AssetStudioGUI/Studio.cs | 410 +- AssetStudioUtility/ACL/ACL.cs | 16 +- AssetStudioUtility/ACL/ACLExtensions.cs | 8 +- AssetStudioUtility/AnimationClipConverter.cs | 499 -- AssetStudioUtility/AnimationClipExtensions.cs | 250 - AssetStudioUtility/AssetStudioUtility.csproj | 18 +- AssetStudioUtility/AudioClipConverter.cs | 2 +- AssetStudioUtility/ConsoleHelper.cs | 21 +- AssetStudioUtility/FontHelper.cs | 10 + AssetStudioUtility/ModelConverter.cs | 63 +- AssetStudioUtility/ShaderConverter.cs | 16 +- AssetStudioUtility/SpriteHelper.cs | 4 +- AssetStudioUtility/Texture2DConverter.cs | 114 +- .../Texture2DDecoderNative.rc | 99 - .../Texture2DDecoderNative.vcxproj | 207 - .../Texture2DDecoderNative.vcxproj.filters | 113 - Texture2DDecoderNative/astc.cpp | 1148 ---- Texture2DDecoderNative/astc.h | 8 - Texture2DDecoderNative/atc.cpp | 91 - Texture2DDecoderNative/atc.h | 5 - Texture2DDecoderNative/bcn.cpp | 1135 ---- Texture2DDecoderNative/bcn.h | 20 - Texture2DDecoderNative/bool32_t.h | 5 - Texture2DDecoderNative/color.h | 87 - Texture2DDecoderNative/cpp.hint | 1 - Texture2DDecoderNative/crunch.cpp | 34 - Texture2DDecoderNative/crunch.h | 5 - Texture2DDecoderNative/crunch/crn_decomp.h | 4843 ----------------- Texture2DDecoderNative/crunch/crnlib.h | 645 --- Texture2DDecoderNative/dllexport.h | 56 - Texture2DDecoderNative/dllmain.cpp | 174 - Texture2DDecoderNative/endianness.h | 180 - Texture2DDecoderNative/etc.cpp | 443 -- Texture2DDecoderNative/etc.h | 15 - Texture2DDecoderNative/fp16.h | 36 - Texture2DDecoderNative/fp16/bitcasts.h | 76 - Texture2DDecoderNative/fp16/fp16.h | 451 -- Texture2DDecoderNative/pvrtc.cpp | 248 - Texture2DDecoderNative/pvrtc.h | 29 - Texture2DDecoderNative/resource.h | 14 - Texture2DDecoderNative/unitycrunch.cpp | 34 - Texture2DDecoderNative/unitycrunch.h | 5 - .../unitycrunch/crn_decomp.h | 3821 ------------- Texture2DDecoderNative/unitycrunch/crn_defs.h | 291 - Texture2DDecoderNative/unitycrunch/crnlib.h | 640 --- Texture2DDecoderWrapper/T2DDll.cs | 9 - .../Texture2DDecoderWrapper.csproj | 17 - .../TextureDecoder.PInvoke.cs | 90 - Texture2DDecoderWrapper/TextureDecoder.cs | 262 - 178 files changed, 5213 insertions(+), 23780 deletions(-) delete mode 100644 AssetStudio.PInvoke/Utf8StringHandle.cs create mode 100644 AssetStudio/AssetGroupOption.cs create mode 100644 AssetStudio/AssetsHelper.cs create mode 100644 AssetStudio/BlockStream.cs delete mode 100644 AssetStudio/CABManager.cs rename AssetStudio/{Game => }/Crypto/AES.cs (100%) create mode 100644 AssetStudio/Crypto/BlkUtils.cs create mode 100644 AssetStudio/Crypto/CNUnity.cs create mode 100644 AssetStudio/Crypto/CryptoHelper.cs rename AssetStudio/{Game => }/Crypto/MT19937_64.cs (76%) create mode 100644 AssetStudio/Crypto/Mr0kUtils.cs rename AssetStudio/{Game => }/Crypto/XORShift128.cs (54%) create mode 100644 AssetStudio/CryptoStream.cs create mode 100644 AssetStudio/ExportTypeList.cs delete mode 100644 AssetStudio/Extensions/BinaryReaderExtensions.cs delete mode 100644 AssetStudio/Extensions/BinaryWriterExtensions.cs delete mode 100644 AssetStudio/Extensions/BitConverterExtensions.cs create mode 100644 AssetStudio/Extensions/ByteArrayExtensions.cs delete mode 100644 AssetStudio/Extensions/PrimitiveExtensions.cs delete mode 100644 AssetStudio/Extensions/StringBuilderExtensions.cs delete mode 100644 AssetStudio/Game/BH3/WMVFile.cs delete mode 100644 AssetStudio/Game/CB1/CB1File.cs delete mode 100644 AssetStudio/Game/CBX/CBXFile.cs delete mode 100644 AssetStudio/Game/Crypto/Blk.cs delete mode 100644 AssetStudio/Game/Crypto/Crypto.cs delete mode 100644 AssetStudio/Game/Crypto/Mark.cs delete mode 100644 AssetStudio/Game/Crypto/Mr0k.cs delete mode 100644 AssetStudio/Game/GI/GIFile.cs delete mode 100644 AssetStudio/Game/GI/Mhy0File.cs delete mode 100644 AssetStudio/Game/GameFile.cs delete mode 100644 AssetStudio/Game/SR_CB3/BlocksFile.cs delete mode 100644 AssetStudio/Game/TOT/TOTFile.cs delete mode 100644 AssetStudio/IYAMLExportable.cs create mode 100644 AssetStudio/Keys.json delete mode 100644 AssetStudio/Math/Float.cs create mode 100644 AssetStudio/Mhy0File.cs create mode 100644 AssetStudio/UnityCNKeyManager.cs delete mode 100644 AssetStudio/YAML/Base/Emitter.cs delete mode 100644 AssetStudio/YAML/Base/MappingStyle.cs delete mode 100644 AssetStudio/YAML/Base/MetaType.cs delete mode 100644 AssetStudio/YAML/Base/ScalarStyle.cs delete mode 100644 AssetStudio/YAML/Base/ScalarType.cs delete mode 100644 AssetStudio/YAML/Base/SequenceStyle.cs delete mode 100644 AssetStudio/YAML/Base/YAMLDocument.cs delete mode 100644 AssetStudio/YAML/Base/YAMLMappingNode.cs delete mode 100644 AssetStudio/YAML/Base/YAMLNode.cs delete mode 100644 AssetStudio/YAML/Base/YAMLNodeType.cs delete mode 100644 AssetStudio/YAML/Base/YAMLScalarNode.cs delete mode 100644 AssetStudio/YAML/Base/YAMLSequenceNode.cs delete mode 100644 AssetStudio/YAML/Base/YAMLTag.cs delete mode 100644 AssetStudio/YAML/Base/YAMLWriter.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/ArrayYAMLExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/EmitterExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/IDictionaryExportYAMLExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/IDictionaryYAMLExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/IEnumerableYAMLExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/IListYAMLExtensions.cs delete mode 100644 AssetStudio/YAML/Utils/Extensions/YAMLMappingNodeExtensions.cs create mode 100644 AssetStudioCLI/App.config create mode 100644 AssetStudioCLI/Options.cs create mode 100644 AssetStudioGUI/CNUnityForm.Designer.cs create mode 100644 AssetStudioGUI/CNUnityForm.cs create mode 100644 AssetStudioGUI/CNUnityForm.resx delete mode 100644 AssetStudioUtility/AnimationClipConverter.cs delete mode 100644 AssetStudioUtility/AnimationClipExtensions.cs create mode 100644 AssetStudioUtility/FontHelper.cs delete mode 100644 Texture2DDecoderNative/Texture2DDecoderNative.rc delete mode 100644 Texture2DDecoderNative/Texture2DDecoderNative.vcxproj delete mode 100644 Texture2DDecoderNative/Texture2DDecoderNative.vcxproj.filters delete mode 100644 Texture2DDecoderNative/astc.cpp delete mode 100644 Texture2DDecoderNative/astc.h delete mode 100644 Texture2DDecoderNative/atc.cpp delete mode 100644 Texture2DDecoderNative/atc.h delete mode 100644 Texture2DDecoderNative/bcn.cpp delete mode 100644 Texture2DDecoderNative/bcn.h delete mode 100644 Texture2DDecoderNative/bool32_t.h delete mode 100644 Texture2DDecoderNative/color.h delete mode 100644 Texture2DDecoderNative/cpp.hint delete mode 100644 Texture2DDecoderNative/crunch.cpp delete mode 100644 Texture2DDecoderNative/crunch.h delete mode 100644 Texture2DDecoderNative/crunch/crn_decomp.h delete mode 100644 Texture2DDecoderNative/crunch/crnlib.h delete mode 100644 Texture2DDecoderNative/dllexport.h delete mode 100644 Texture2DDecoderNative/dllmain.cpp delete mode 100644 Texture2DDecoderNative/endianness.h delete mode 100644 Texture2DDecoderNative/etc.cpp delete mode 100644 Texture2DDecoderNative/etc.h delete mode 100644 Texture2DDecoderNative/fp16.h delete mode 100644 Texture2DDecoderNative/fp16/bitcasts.h delete mode 100644 Texture2DDecoderNative/fp16/fp16.h delete mode 100644 Texture2DDecoderNative/pvrtc.cpp delete mode 100644 Texture2DDecoderNative/pvrtc.h delete mode 100644 Texture2DDecoderNative/resource.h delete mode 100644 Texture2DDecoderNative/unitycrunch.cpp delete mode 100644 Texture2DDecoderNative/unitycrunch.h delete mode 100644 Texture2DDecoderNative/unitycrunch/crn_decomp.h delete mode 100644 Texture2DDecoderNative/unitycrunch/crn_defs.h delete mode 100644 Texture2DDecoderNative/unitycrunch/crnlib.h delete mode 100644 Texture2DDecoderWrapper/T2DDll.cs delete mode 100644 Texture2DDecoderWrapper/Texture2DDecoderWrapper.csproj delete mode 100644 Texture2DDecoderWrapper/TextureDecoder.PInvoke.cs delete mode 100644 Texture2DDecoderWrapper/TextureDecoder.cs diff --git a/AssetStudio.PInvoke/AssetStudio.PInvoke.csproj b/AssetStudio.PInvoke/AssetStudio.PInvoke.csproj index 9136396..90ac680 100644 --- a/AssetStudio.PInvoke/AssetStudio.PInvoke.csproj +++ b/AssetStudio.PInvoke/AssetStudio.PInvoke.csproj @@ -1,11 +1,11 @@ - net6.0 + net7.0 true - 0.18.60 - 0.18.60 - 0.18.60 + 0.80.30 + 0.80.30 + 0.80.30 Copyright © Perfare 2020-2022; Copyright © hozuki 2020 embedded diff --git a/AssetStudio.PInvoke/DllLoader.cs b/AssetStudio.PInvoke/DllLoader.cs index b4e85ea..88265d6 100644 --- a/AssetStudio.PInvoke/DllLoader.cs +++ b/AssetStudio.PInvoke/DllLoader.cs @@ -6,7 +6,7 @@ using System.Runtime.InteropServices; namespace AssetStudio.PInvoke { - public static class DllLoader + public static partial class DllLoader { public static void PreloadDll(string dllName) @@ -37,7 +37,7 @@ namespace AssetStudio.PInvoke return directedDllDir; } - private static class Win32 + private static partial class Win32 { internal static void LoadDll(string dllDir, string dllName) @@ -46,9 +46,9 @@ namespace AssetStudio.PInvoke var directedDllPath = Path.Combine(dllDir, dllFileName); // Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory. - var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); + var hLibrary = LoadLibraryEx(directedDllPath, nint.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); - if (hLibrary == IntPtr.Zero) + if (hLibrary == nint.Zero) { var errorCode = Marshal.GetLastWin32Error(); var exception = new Win32Exception(errorCode); @@ -59,15 +59,15 @@ namespace AssetStudio.PInvoke // HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); // HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); - [DllImport("kernel32.dll", SetLastError = true)] - private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags); + [LibraryImport("kernel32.dll", EntryPoint = "LoadLibraryExA", SetLastError = true, StringMarshalling = StringMarshalling.Utf8)] + private static partial IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags); private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000; private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100; } - private static class Posix + private static partial class Posix { internal static void LoadDll(string dllDir, string dllName) @@ -93,7 +93,7 @@ namespace AssetStudio.PInvoke const int ldFlags = RTLD_NOW | RTLD_GLOBAL; var hLibrary = DlOpen(directedDllPath, ldFlags); - if (hLibrary == IntPtr.Zero) + if (hLibrary == nint.Zero) { var pErrStr = DlError(); // `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325), @@ -107,12 +107,12 @@ namespace AssetStudio.PInvoke // OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms. // void *dlopen(const char *filename, int flag); - [DllImport("libdl", EntryPoint = "dlopen")] - private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags); + [LibraryImport("libdl", EntryPoint = "dlopen", StringMarshalling = StringMarshalling.Utf8)] + private static partial nint DlOpen(string fileName, int flags); // char *dlerror(void); - [DllImport("libdl", EntryPoint = "dlerror")] - private static extern IntPtr DlError(); + [LibraryImport("libdl", EntryPoint = "dlerror")] + private static partial nint DlError(); private const int RTLD_LAZY = 0x1; private const int RTLD_NOW = 0x2; diff --git a/AssetStudio.PInvoke/Utf8StringHandle.cs b/AssetStudio.PInvoke/Utf8StringHandle.cs deleted file mode 100644 index 96a7719..0000000 --- a/AssetStudio.PInvoke/Utf8StringHandle.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Text; -using Microsoft.Win32.SafeHandles; - -namespace AssetStudio.PInvoke -{ - // Generally the technique from Steamworks.NET - public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid - { - - static Utf8StringHandle() - { - Utf8 = new UTF8Encoding(false); - } - - public Utf8StringHandle(string str) - : base(true) - { - IntPtr buffer; - - if (str == null) - { - buffer = IntPtr.Zero; - } - else - { - if (str.Length == 0) - { - buffer = Marshal.AllocHGlobal(1); - - unsafe - { - *(byte*)buffer = 0; - } - } - else - { - var strlen = Utf8.GetByteCount(str); - var strBuffer = new byte[strlen + 1]; - - Utf8.GetBytes(str, 0, str.Length, strBuffer, 0); - - buffer = Marshal.AllocHGlobal(strBuffer.Length); - - Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length); - } - } - - SetHandle(buffer); - } - - public static string ReadUtf8StringFromPointer(IntPtr lpstr) - { - if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1)) - { - return null; - } - - var byteCount = 0; - - unsafe - { - var p = (byte*)lpstr.ToPointer(); - - while (*p != 0) - { - byteCount += 1; - p += 1; - } - } - - if (byteCount == 0) - { - return string.Empty; - } - - var strBuffer = new byte[byteCount]; - - Marshal.Copy(lpstr, strBuffer, 0, byteCount); - - var str = Utf8.GetString(strBuffer); - - return str; - } - - protected override bool ReleaseHandle() - { - if (!IsInvalid) - { - Marshal.FreeHGlobal(handle); - } - - return true; - } - - private static readonly UTF8Encoding Utf8; - - } -} diff --git a/AssetStudio.sln b/AssetStudio.sln index 298e168..54b2ce2 100644 --- a/AssetStudio.sln +++ b/AssetStudio.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 +VisualStudioVersion = 17.4.33205.214 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}" EndProject @@ -16,16 +16,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioGUI", "AssetStud EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}" - ProjectSection(ProjectDependencies) = postProject - {29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioCLI", "AssetStudioCLI\AssetStudioCLI.csproj", "{5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioCLI", "AssetStudioCLI\AssetStudioCLI.csproj", "{D35262CD-E063-4203-A9D2-C1BB82B6C598}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -97,18 +90,6 @@ Global {65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.Build.0 = Release|Any CPU {65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.ActiveCfg = Release|Any CPU {65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.Build.0 = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.Build.0 = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.ActiveCfg = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.Build.0 = Debug|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.Build.0 = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.ActiveCfg = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.Build.0 = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.ActiveCfg = Release|Any CPU - {6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.Build.0 = Release|Any CPU {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32 {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32 {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64 @@ -121,30 +102,18 @@ Global {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64 {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32 {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.Build.0 = Debug|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.Build.0 = Release|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32 - {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32 - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|x64.ActiveCfg = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|x64.Build.0 = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|x86.ActiveCfg = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Debug|x86.Build.0 = Debug|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|Any CPU.Build.0 = Release|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|x64.ActiveCfg = Release|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|x64.Build.0 = Release|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|x86.ActiveCfg = Release|Any CPU - {5B2D8C81-7DE2-429C-AF90-B7C71D91F3B6}.Release|x86.Build.0 = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|x64.ActiveCfg = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|x64.Build.0 = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|x86.ActiveCfg = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Debug|x86.Build.0 = Debug|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|Any CPU.Build.0 = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|x64.ActiveCfg = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|x64.Build.0 = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|x86.ActiveCfg = Release|Any CPU + {D35262CD-E063-4203-A9D2-C1BB82B6C598}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AssetStudio/AssetEntry.cs b/AssetStudio/AssetEntry.cs index 7f5a580..6ef42a4 100644 --- a/AssetStudio/AssetEntry.cs +++ b/AssetStudio/AssetEntry.cs @@ -2,10 +2,10 @@ { public class AssetEntry { - public string Name; - public string Container; - public string Source; - public long PathID; - public ClassIDType Type; + public string Name { get; set; } + public string Container { get; set; } + public string Source { get; set; } + public long PathID { get; set; } + public ClassIDType Type { get; set; } } } diff --git a/AssetStudio/AssetGroupOption.cs b/AssetStudio/AssetGroupOption.cs new file mode 100644 index 0000000..d864251 --- /dev/null +++ b/AssetStudio/AssetGroupOption.cs @@ -0,0 +1,10 @@ +namespace AssetStudio +{ + public enum AssetGroupOption + { + ByType, + ByContainer, + BySource, + None + } +} diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index 00d74de..9e6d6e4 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -1,17 +1,23 @@ - net6.0 - 0.18.60 - 0.18.60 - 0.18.60 + net7.0 + 0.80.30 + 0.80.30 + 0.80.30 Copyright © Razmoth 2022; Copyright © Perfare 2018-2022 - embedded + embedded - + - - + + + + + PreserveNewest + + + diff --git a/AssetStudio/AssetsHelper.cs b/AssetStudio/AssetsHelper.cs new file mode 100644 index 0000000..811b765 --- /dev/null +++ b/AssetStudio/AssetsHelper.cs @@ -0,0 +1,436 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Threading; +using System.Globalization; +using System.Xml.Linq; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json; +using System.Text.RegularExpressions; + +namespace AssetStudio +{ + public static class AssetsHelper + { + public const string CABMapName = "Maps"; + + public static CancellationTokenSource tokenSource = new CancellationTokenSource(); + public static AssetsManager assetsManager = new AssetsManager() { Silent = true, SkipProcess = true, ResolveDependencies = false }; + + public static string BaseFolder = ""; + public static Dictionary CABMap = new Dictionary(StringComparer.OrdinalIgnoreCase); + public static Dictionary> Offsets = new Dictionary>(); + + public static void Clear() + { + CABMap.Clear(); + Offsets.Clear(); + BaseFolder = ""; + + tokenSource.Dispose(); + tokenSource = new CancellationTokenSource(); + + GC.WaitForPendingFinalizers(); + GC.Collect(); + } + + public static string[] GetMaps() + { + Directory.CreateDirectory(CABMapName); + var files = Directory.GetFiles(CABMapName, "*.bin", SearchOption.TopDirectoryOnly); + return files.Select(x => Path.GetFileNameWithoutExtension(x)).ToArray(); + } + + public static void BuildCABMap(string[] files, string mapName, string baseFolder, Game game) + { + Logger.Info($"Processing..."); + try + { + CABMap.Clear(); + BaseFolder = baseFolder; + assetsManager.Game = game; + for (int i = 0; i < files.Length; i++) + { + var file = files[i]; + assetsManager.LoadFiles(file); + if (assetsManager.assetsFileList.Count > 0) + { + var relativePath = Path.GetRelativePath(BaseFolder, file); + foreach (var assetsFile in assetsManager.assetsFileList) + { + if (tokenSource.IsCancellationRequested) + { + Logger.Info("Building CABMap has been aborted !!"); + return; + } + var dependencies = assetsFile.m_Externals.Select(x => x.fileName).ToArray(); + var entry = new Entry() + { + Path = relativePath, + Offset = assetsFile.offset, + Dependencies = dependencies + }; + + CABMap.TryAdd(assetsFile.fileName, new()); + CABMap[assetsFile.fileName] = entry; + } + Logger.Info($"Processed {Path.GetFileName(file)}"); + } + assetsManager.Clear(); + } + + CABMap = CABMap.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase); + var outputFile = new FileInfo(Path.Combine(CABMapName, $"{mapName}.bin")); + + outputFile.Directory.Create(); + + using (var binaryFile = outputFile.Create()) + using (var writer = new BinaryWriter(binaryFile)) + { + writer.Write(BaseFolder); + writer.Write(CABMap.Count); + foreach (var kv in CABMap) + { + writer.Write(kv.Key); + writer.Write(kv.Value.Path); + writer.Write(kv.Value.Offset); + writer.Write(kv.Value.Dependencies.Length); + foreach (var cab in kv.Value.Dependencies) + { + writer.Write(cab); + } + } + } + + Logger.Info($"CABMap build successfully !!"); + } + catch (Exception e) + { + Logger.Warning($"CABMap was not build, {e.Message}{e.StackTrace}"); + } + } + + public static void LoadMap(string mapName) + { + Logger.Info($"Loading {mapName}"); + try + { + CABMap.Clear(); + using (var fs = File.OpenRead(Path.Combine(CABMapName, $"{mapName}.bin"))) + using (var reader = new BinaryReader(fs)) + { + BaseFolder = reader.ReadString(); + var count = reader.ReadInt32(); + for (int i = 0; i < count; i++) + { + var cab = reader.ReadString(); + var path = reader.ReadString(); + var offset = reader.ReadInt64(); + var depCount = reader.ReadInt32(); + var dependencies = new List(); + for (int j = 0; j < depCount; j++) + { + var dependancy = reader.ReadString(); + dependencies.Add(dependancy); + } + var entry = new Entry() + { + Path = path, + Offset = offset, + Dependencies = dependencies.ToArray() + }; + CABMap.Add(cab, entry); + } + } + Logger.Info($"Loaded {mapName} !!"); + } + catch (Exception e) + { + Logger.Warning($"{mapName} was not loaded, {e.Message}"); + } + } + + public static AssetEntry[] BuildAssetMap(string[] files, Game game, ClassIDType[] typeFilters = null, Regex[] nameFilters = null, Regex[] containerFilters = null) + { + assetsManager.Game = game; + var assets = new List(); + for (int i = 0; i < files.Length; i++) + { + var file = files[i]; + assetsManager.LoadFiles(file); + if (assetsManager.assetsFileList.Count > 0) + { + var containers = new List<(PPtr, string)>(); + var mihoyoBinDataNames = new List<(PPtr, string)>(); + var objectAssetItemDic = new Dictionary(); + var animators = new List<(PPtr, AssetEntry)>(); + foreach (var assetsFile in assetsManager.assetsFileList) + { + assetsFile.m_Objects = ObjectInfo.Filter(assetsFile.m_Objects); + + foreach (var objInfo in assetsFile.m_Objects) + { + var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo, game); + var obj = new Object(objectReader); + var asset = new AssetEntry() + { + Source = file, + PathID = objectReader.m_PathID, + Type = objectReader.type, + Container = "" + }; + + var exportable = true; + switch (objectReader.type) + { + case ClassIDType.AssetBundle: + var assetBundle = new AssetBundle(objectReader); + foreach (var m_Container in assetBundle.m_Container) + { + var preloadIndex = m_Container.Value.preloadIndex; + var preloadSize = m_Container.Value.preloadSize; + var preloadEnd = preloadIndex + preloadSize; + for (int k = preloadIndex; k < preloadEnd; k++) + { + containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key)); + } + } + obj = null; + asset.Name = assetBundle.m_Name; + exportable = false; + break; + case ClassIDType.GameObject: + var gameObject = new GameObject(objectReader); + obj = gameObject; + asset.Name = gameObject.m_Name; + exportable = false; + break; + case ClassIDType.Shader: + asset.Name = objectReader.ReadAlignedString(); + if (string.IsNullOrEmpty(asset.Name)) + { + var m_parsedForm = new SerializedShader(objectReader); + asset.Name = m_parsedForm.m_Name; + } + break; + case ClassIDType.Animator: + var component = new PPtr(objectReader); + animators.Add((component, asset)); + break; + case ClassIDType.MiHoYoBinData: + var MiHoYoBinData = new MiHoYoBinData(objectReader); + obj = MiHoYoBinData; + exportable = MiHoYoBinData.Exportable; + break; + case ClassIDType.IndexObject: + var indexObject = new IndexObject(objectReader); + obj = null; + foreach (var index in indexObject.AssetMap) + { + mihoyoBinDataNames.Add((index.Value.Object, index.Key)); + } + asset.Name = "IndexObject"; + break; + default: + asset.Name = objectReader.ReadAlignedString(); + break; + } + if (obj != null) + { + objectAssetItemDic.Add(obj, asset); + assetsFile.AddObject(obj); + } + var isMatchRegex = nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(asset.Name) || asset.Type == ClassIDType.Animator); + var isFilteredType = typeFilters.IsNullOrEmpty() || typeFilters.Contains(asset.Type) || asset.Type == ClassIDType.Animator; + if (isMatchRegex && isFilteredType && exportable) + { + assets.Add(asset); + } + } + } + foreach ((var pptr, var asset) in animators) + { + if (pptr.TryGet(out var gameObject) && (nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(gameObject.m_Name))) && (typeFilters.IsNullOrEmpty() || typeFilters.Contains(asset.Type))) + { + asset.Name = gameObject.m_Name; + } + } + foreach((var pptr, var name) in mihoyoBinDataNames) + { + if (pptr.TryGet(out var miHoYoBinData)) + { + var asset = objectAssetItemDic[miHoYoBinData]; + if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash)) + { + asset.Name = name; + asset.Container = hash.ToString(); + } + else asset.Name = $"BinFile #{asset.PathID}"; + } + } + foreach ((var pptr, var container) in containers) + { + if (pptr.TryGet(out var obj)) + { + var item = objectAssetItemDic[obj]; + if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container))) + { + item.Container = container; + } + else + { + assets.Remove(item); + } + } + } + Logger.Info($"Processed {Path.GetFileName(file)}"); + } + assetsManager.Clear(); + } + if (game.Type.IsGISubGroup() && assets.Count > 0) + { + Logger.Info("Updating Containers..."); + foreach (var asset in assets) + { + if (int.TryParse(asset.Container, out var value)) + { + var last = unchecked((uint)value); + var path = ResourceIndex.GetAssetPath(last); + if (!string.IsNullOrEmpty(path)) + { + asset.Container = path; + if (asset.Type == ClassIDType.MiHoYoBinData) + { + asset.Name = Path.GetFileNameWithoutExtension(path); + } + } + } + } + Logger.Info("Updated !!"); + } + return assets.ToArray(); + } + + public static void ExportAssetsMap(AssetEntry[] toExportAssets, string name, string savePath, ExportListType exportListType) + { + ThreadPool.QueueUserWorkItem(state => + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + + Progress.Reset(); + + string filename; + switch (exportListType) + { + case ExportListType.XML: + filename = Path.Combine(savePath, $"{name}.xml"); + var doc = new XDocument( + new XElement("Assets", + new XAttribute("filename", filename), + new XAttribute("createdAt", DateTime.UtcNow.ToString("s")), + toExportAssets.Select( + asset => new XElement("Asset", + new XElement("Name", asset.Name), + new XElement("Container", asset.Container), + new XElement("Type", new XAttribute("id", (int)asset.Type), asset.Type.ToString()), + new XElement("PathID", asset.PathID), + new XElement("Source", asset.Source) + ) + ) + ) + ); + doc.Save(filename); + break; + case ExportListType.JSON: + filename = Path.Combine(savePath, $"{name}.json"); + using (StreamWriter file = File.CreateText(filename)) + { + var serializer = new JsonSerializer() { Formatting = Formatting.Indented }; + serializer.Converters.Add(new StringEnumConverter()); + serializer.Serialize(file, toExportAssets); + } + break; + } + + Logger.Info($"Finished exporting asset list with {toExportAssets.Length} items."); + Logger.Info($"AssetMap build successfully !!"); + }); + } + + public static void AddCABOffsets(string[] path, List cabs) + { + for (int i = 0; i < cabs.Count; i++) + { + var cab = cabs[i]; + if (CABMap.TryGetValue(cab, out var entry)) + { + if (!path.Contains(entry.Path)) + { + var fullPath = Path.Combine(BaseFolder, entry.Path); + if (!Offsets.ContainsKey(fullPath)) + { + Offsets.Add(fullPath, new HashSet()); + } + Offsets[fullPath].Add(entry.Offset); + } + foreach (var dep in entry.Dependencies) + { + if (!cabs.Contains(dep)) + cabs.Add(dep); + } + } + } + } + + public static bool FindCAB(string path, out List cabs) + { + cabs = new List(); + var relativePath = Path.GetRelativePath(BaseFolder, path); + foreach (var kv in CABMap) + { + if (kv.Value.Path.Equals(relativePath)) + { + cabs.Add(kv.Key); + } + } + return cabs.Count != 0; + } + + public static string[] ProcessFiles(string[] files) + { + foreach (var file in files) + { + if (!Offsets.ContainsKey(file)) + { + Offsets.Add(file, new HashSet()); + } + if (FindCAB(file, out var cabs)) + { + AddCABOffsets(files, cabs); + } + } + return Offsets.Keys.ToArray(); + } + + public static string[] ProcessDependencies(string[] files) + { + if (CABMap.Count == 0) + { + Logger.Warning("CABMap is not build, skip resolving dependencies..."); + } + else + { + Logger.Info("Resolving Dependencies..."); + files = ProcessFiles(files); + } + return files; + } + public record Entry + { + public string Path { get; set; } + public long Offset { get; set; } + public string[] Dependencies { get; set; } + } + } +} diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index 2d5117e..f7e5881 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -1,9 +1,11 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; +using System.Threading; using static AssetStudio.ImportHelper; namespace AssetStudio @@ -11,8 +13,11 @@ namespace AssetStudio public class AssetsManager { public Game Game; - public bool ResolveDependancies; + public bool Silent = false; + public bool SkipProcess = false; + public bool ResolveDependencies = false; public string SpecifyUnityVersion; + public CancellationTokenSource tokenSource = new CancellationTokenSource(); public List assetsFileList = new List(); internal Dictionary assetsFileIndexCache = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -20,19 +25,49 @@ namespace AssetStudio private List importFiles = new List(); private HashSet importFilesHash = new HashSet(StringComparer.OrdinalIgnoreCase); + private HashSet noexistFiles = new HashSet(StringComparer.OrdinalIgnoreCase); private HashSet assetsFileListHash = new HashSet(StringComparer.OrdinalIgnoreCase); public void LoadFiles(params string[] files) { - if (ResolveDependancies) - files = CABManager.ProcessDependencies(files); - Load(files); + if (Silent) + { + Logger.Silent = true; + Progress.Silent = true; + } + + var path = Path.GetDirectoryName(Path.GetFullPath(files[0])); + MergeSplitAssets(path); + var toReadFile = ProcessingSplitFiles(files.ToList()); + if (ResolveDependencies) + toReadFile = AssetsHelper.ProcessDependencies(toReadFile); + Load(toReadFile); + + if (Silent) + { + Logger.Silent = false; + Progress.Silent = false; + } } public void LoadFolder(string path) { - var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).ToArray(); - Load(files); + if (Silent) + { + Logger.Silent = true; + Progress.Silent = true; + } + + MergeSplitAssets(path, true); + var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).ToList(); + var toReadFile = ProcessingSplitFiles(files); + Load(toReadFile); + + if (Silent) + { + Logger.Silent = false; + Progress.Silent = false; + } } private void Load(string[] files) @@ -49,20 +84,29 @@ namespace AssetStudio { LoadFile(importFiles[i]); Progress.Report(i + 1, importFiles.Count); + if (tokenSource.IsCancellationRequested) + { + Logger.Info("Loading files has been aborted !!"); + break; + } } importFiles.Clear(); importFilesHash.Clear(); + noexistFiles.Clear(); assetsFileListHash.Clear(); - CABManager.offsets.Clear(); - ReadAssets(); - ProcessAssets(); + if (!SkipProcess && !tokenSource.IsCancellationRequested) + { + ReadAssets(); + ProcessAssets(); + } } private void LoadFile(string fullName) { - var reader = new FileReader(fullName, Game); + var reader = new FileReader(fullName); + reader = reader.PreProcessing(Game); LoadFile(reader); } @@ -76,9 +120,6 @@ namespace AssetStudio case FileType.BundleFile: LoadBundleFile(reader); break; - case FileType.GameFile: - LoadGameFile(reader); - break; case FileType.WebFile: LoadWebFile(reader); break; @@ -91,6 +132,15 @@ namespace AssetStudio case FileType.ZipFile: LoadZipFile(reader); break; + case FileType.BlockFile: + LoadBlockFile(reader); + break; + case FileType.BlkFile: + LoadBlkFile(reader); + break; + case FileType.Mhy0File: + LoadMhy0File(reader); + break; } } @@ -98,13 +148,46 @@ namespace AssetStudio { if (!assetsFileListHash.Contains(reader.FileName)) { - Logger.Info($"Loading {reader.FileName}"); + Logger.Info($"Loading {reader.FullPath}"); try { - var assetsFile = new SerializedFile(reader, this, reader.FullPath); + var assetsFile = new SerializedFile(reader, this); CheckStrippedVersion(assetsFile); assetsFileList.Add(assetsFile); assetsFileListHash.Add(assetsFile.fileName); + + if (ResolveDependencies) + { + foreach (var sharedFile in assetsFile.m_Externals) + { + var sharedFileName = sharedFile.fileName; + + if (!importFilesHash.Contains(sharedFileName)) + { + var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName); + if (!noexistFiles.Contains(sharedFilePath)) + { + if (!File.Exists(sharedFilePath)) + { + var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories); + if (findFiles.Length > 0) + { + sharedFilePath = findFiles[0]; + } + } + if (File.Exists(sharedFilePath)) + { + importFiles.Add(sharedFilePath); + importFilesHash.Add(sharedFileName); + } + else + { + noexistFiles.Add(sharedFilePath); + } + } + } + } + } } catch (Exception e) { @@ -119,7 +202,7 @@ namespace AssetStudio } } - private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null) + private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null, long originalOffset = 0) { if (!assetsFileListHash.Contains(reader.FileName)) { @@ -127,6 +210,7 @@ namespace AssetStudio { var assetsFile = new SerializedFile(reader, this); assetsFile.originalPath = originalPath; + assetsFile.offset = originalOffset; if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7) { assetsFile.SetVersion(unityVersion); @@ -145,19 +229,19 @@ namespace AssetStudio Logger.Info($"Skipping {originalPath} ({reader.FileName})"); } - private void LoadBundleFile(FileReader reader, string originalPath = null) + private void LoadBundleFile(FileReader reader, string originalPath = null, long originalOffset = 0) { Logger.Info("Loading " + reader.FullPath); try { - var bundleFile = new BundleFile(reader); - foreach (var file in bundleFile.FileList) + var bundleFile = new BundleFile(reader, Game); + foreach (var file in bundleFile.fileList) { var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName); var subReader = new FileReader(dummyPath, file.stream); if (subReader.FileType == FileType.AssetsFile) { - LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision); + LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision, originalOffset); } else { @@ -165,6 +249,10 @@ namespace AssetStudio } } } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mr0k)} but got {Game.Name} ({Game.GetType().Name}) !!"); + } catch (Exception e) { var str = $"Error while reading bundle file {reader.FullPath}"; @@ -316,37 +404,132 @@ namespace AssetStudio reader.Dispose(); } } - - private void LoadGameFile(FileReader reader) + private void LoadBlockFile(FileReader reader) { - Logger.Info("Loading " + reader.FileName); + Logger.Info("Loading " + reader.FullPath); try { - reader.BundlePos = CABManager.offsets.TryGetValue(reader.FullPath, out var list) ? list.ToArray() : Array.Empty(); - var gameFile = new GameFile(reader); - foreach (var bundle in gameFile.Bundles) + var offsets = AssetsHelper.Offsets.TryGetValue(reader.FullPath, out var list) ? list.ToArray() : Array.Empty(); + using var stream = new BlockStream(reader.BaseStream, 0); + if (!offsets.IsNullOrEmpty()) { - foreach (var file in bundle.Value) + foreach (var offset in offsets) { - var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName); - var cabReader = new FileReader(dummyPath, file.stream, Game); - if (cabReader.FileType == FileType.AssetsFile) - { - var assetsFile = new SerializedFile(cabReader, this, reader.FullPath); - CheckStrippedVersion(assetsFile); - assetsFileList.Add(assetsFile); - assetsFileListHash.Add(assetsFile.fileName); - } - else - { - resourceFileReaders[file.fileName] = cabReader; //TODO - } + stream.Offset = offset; + var dummyPath = Path.Combine("//?/block:/", reader.FileName, offset.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + LoadBundleFile(subReader, reader.FullPath, offset); } } + else + { + do + { + stream.Offset = stream.RelativePosition; + var dummyPath = Path.Combine("//?/block:/", reader.FileName, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition); + } while (stream.Remaining > 0); + } } catch (Exception e) { - Logger.Error($"Error while reading file {reader.FileName}", e); + Logger.Error($"Error while reading block file {reader.FileName}", e); + } + finally + { + reader.Dispose(); + } + } + private void LoadBlkFile(FileReader reader) + { + Logger.Info("Loading " + reader.FullPath); + try + { + var offsets = AssetsHelper.Offsets.TryGetValue(reader.FullPath, out var list) ? list.ToArray() : Array.Empty(); + using var stream = BlkUtils.Decrypt(reader, (Blk)Game); + if (!offsets.IsNullOrEmpty()) + { + foreach (var offset in offsets) + { + stream.Offset = offset; + var dummyPath = Path.Combine("//?/blk:/", reader.FileName, offset.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + switch (subReader.FileType) + { + case FileType.BundleFile: + LoadBundleFile(subReader, reader.FullPath, offset); + break; + case FileType.Mhy0File: + LoadMhy0File(subReader, reader.FullPath, offset); + break; + } + } + } + else + { + do + { + stream.Offset = stream.RelativePosition; + var dummyPath = Path.Combine("//?/blk:/", reader.FileName, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + switch (subReader.FileType) + { + case FileType.BundleFile: + LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition); + break; + case FileType.Mhy0File: + LoadMhy0File(subReader, reader.FullPath, stream.RelativePosition); + break; + } + } while (stream.Remaining > 0); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Blk)} but got {Game.Name} ({Game.GetType().Name}) !!"); + } + catch (Exception e) + { + Logger.Error($"Error while reading blk file {reader.FileName}", e); + } + finally + { + reader.Dispose(); + } + } + private void LoadMhy0File(FileReader reader, string originalPath = null, long originalOffset = 0) + { + Logger.Info("Loading " + reader.FullPath); + try + { + var mhy0File = new Mhy0File(reader, reader.FullPath, (Mhy0)Game); + foreach (var file in mhy0File.fileList) + { + var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName); + var cabReader = new FileReader(dummyPath, file.stream); + if (cabReader.FileType == FileType.AssetsFile) + { + LoadAssetsFromMemory(cabReader, originalPath ?? reader.FullPath, mhy0File.m_Header.unityRevision, originalOffset); + } + else + { + resourceFileReaders[file.fileName] = cabReader; //TODO + } + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mhy0)} but got {Game.Name} ({Game.GetType().Name}) !!"); + } + catch (Exception e) + { + var str = $"Error while reading mhy0 file {reader.FullPath}"; + if (originalPath != null) + { + str += $" from {Path.GetFileName(originalPath)}"; + } + Logger.Error(str, e); } finally { @@ -382,6 +565,12 @@ namespace AssetStudio resourceFileReaders.Clear(); assetsFileIndexCache.Clear(); + + tokenSource.Dispose(); + tokenSource = new CancellationTokenSource(); + + GC.WaitForPendingFinalizers(); + GC.Collect(); } private void ReadAssets() @@ -395,7 +584,12 @@ namespace AssetStudio { foreach (var objectInfo in assetsFile.m_Objects) { - var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo); + if (tokenSource.IsCancellationRequested) + { + Logger.Info("Reading assets has been aborted !!"); + return; + } + var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo, Game); try { Object obj; @@ -444,7 +638,8 @@ namespace AssetStudio obj = new MeshFilter(objectReader); break; case ClassIDType.MeshRenderer: - if (!Renderer.Parsable) continue; + if (Renderer.Skipped) + goto default; obj = new MeshRenderer(objectReader); break; case ClassIDType.MiHoYoBinData: @@ -466,11 +661,11 @@ namespace AssetStudio obj = new RectTransform(objectReader); break; case ClassIDType.Shader: - if (!Shader.Parsable) continue; obj = new Shader(objectReader); break; case ClassIDType.SkinnedMeshRenderer: - if (!Renderer.Parsable) continue; + if (Renderer.Skipped) + goto default; obj = new SkinnedMeshRenderer(objectReader); break; case ClassIDType.Sprite: @@ -519,12 +714,20 @@ namespace AssetStudio private void ProcessAssets() { + if (tokenSource.IsCancellationRequested) + return; + Logger.Info("Process Assets..."); foreach (var assetsFile in assetsFileList) { foreach (var obj in assetsFile.Objects) { + if (tokenSource.IsCancellationRequested) + { + Logger.Info("Processing assets has been aborted !!"); + return; + } if (obj is GameObject m_GameObject) { foreach (var pptr in m_GameObject.m_Components) @@ -556,7 +759,7 @@ namespace AssetStudio } } else if (obj is SpriteAtlas m_SpriteAtlas) - { + { if (m_SpriteAtlas.m_RenderDataMap.Count > 0) { foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites) diff --git a/AssetStudio/BlockStream.cs b/AssetStudio/BlockStream.cs new file mode 100644 index 0000000..645ac8d --- /dev/null +++ b/AssetStudio/BlockStream.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; + +namespace AssetStudio +{ + public class BlockStream : Stream + { + private readonly Stream _baseStream; + private readonly long _origin; + private long _startPosition; + + public override bool CanRead => _baseStream.CanRead; + public override bool CanSeek => _baseStream.CanSeek; + public override bool CanWrite => false; + + public override long Length => _baseStream.Length - _startPosition; + + public override long Position + { + get => _baseStream.Position - _startPosition; + set => Seek(value, SeekOrigin.Begin); + } + + public long Offset + { + get => _startPosition; + set => _startPosition = value + _origin; + } + + public long RelativePosition => _baseStream.Position - _origin; + public long Remaining => Length - Position; + + public BlockStream(Stream stream, long offset) + { + _baseStream = stream; + _origin = offset; + _startPosition = offset; + Seek(0, SeekOrigin.Begin); + } + + public override long Seek(long offset, SeekOrigin origin) + { + var target = origin switch + { + SeekOrigin.Begin => offset + _startPosition, + SeekOrigin.Current => offset + _baseStream.Position, + SeekOrigin.End => offset + Length, + _ => throw new NotSupportedException() + }; + + _baseStream.Seek(target, SeekOrigin.Begin); + return Position; + } + public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count); + public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(); + public override void SetLength(long value) => throw new NotImplementedException(); + public override void Flush() => throw new NotImplementedException(); + } +} diff --git a/AssetStudio/BundleFile.cs b/AssetStudio/BundleFile.cs index 09025c6..e86e235 100644 --- a/AssetStudio/BundleFile.cs +++ b/AssetStudio/BundleFile.cs @@ -1,7 +1,9 @@ using K4os.Compression.LZ4; using System; +using System.Data; using System.IO; using System.Linq; +using System.Text.RegularExpressions; namespace AssetStudio { @@ -12,14 +14,16 @@ namespace AssetStudio BlocksAndDirectoryInfoCombined = 0x40, BlocksInfoAtTheEnd = 0x80, OldWebPluginCompatibility = 0x100, - BlockInfoNeedPaddingAtStart = 0x200 + BlockInfoNeedPaddingAtStart = 0x200, + CNUnityEncryption = 0x400 } [Flags] public enum StorageBlockFlags { CompressionTypeMask = 0x3f, - Streamed = 0x40 + Streamed = 0x40, + CNUnity = 0x100 } public enum CompressionType @@ -31,6 +35,7 @@ namespace AssetStudio Lzham, Lz4Mr0k } + public class BundleFile { public class Header @@ -60,46 +65,19 @@ namespace AssetStudio public string path; } + private Game Game; + private CNUnity CNUnity; + public Header m_Header; - private StorageBlock[] m_BlocksInfo; private Node[] m_DirectoryInfo; + private StorageBlock[] m_BlocksInfo; - public StreamFile[] FileList; + public StreamFile[] fileList; - public BundleFile(FileReader reader) + public BundleFile(FileReader reader, Game game) { - m_Header = new Header(); - m_Header.signature = reader.ReadStringToNull(); - - if (reader.Game.Name == "BH3") - { - m_Header.version = 6; - m_Header.unityVersion = "5.x.x"; - m_Header.unityRevision = "2017.4.18f1"; - } - else if (reader.Game.Name == "SR_CB2" || reader.Game.Name == "SR_CB3") - { - var readHeader = m_Header.signature != "ENCR"; - - if (!readHeader) - { - m_Header.version = 7; - m_Header.unityVersion = "5.x.x"; - m_Header.unityRevision = "2019.4.32f1"; - } - else - { - m_Header.version = reader.ReadUInt32(); - m_Header.unityVersion = reader.ReadStringToNull(); - m_Header.unityRevision = reader.ReadStringToNull(); - } - } - else - { - m_Header.version = reader.ReadUInt32(); - m_Header.unityVersion = reader.ReadStringToNull(); - m_Header.unityRevision = reader.ReadStringToNull(); - } + Game = game; + m_Header = ReadBundleHeader(reader); switch (m_Header.signature) { case "UnityArchive": @@ -120,10 +98,6 @@ namespace AssetStudio case "UnityFS": case "ENCR": ReadHeader(reader); - if (reader.Game.Name == "ZZZ_CB1") - { - reader.AlignStream(0x10); - } ReadBlocksInfoAndDirectory(reader); using (var blocksStream = CreateBlocksStream(reader.FullPath)) { @@ -134,6 +108,54 @@ namespace AssetStudio } } + private Header ReadBundleHeader(FileReader reader) + { + Header header = new Header(); + header.signature = reader.ReadStringToNull(20); + switch (header.signature) + { + case "UnityFS": + if (Game.Type.IsBH3()) + { + var version = reader.ReadUInt32(); + if (version > 11) + { + XORShift128.InitSeed(version); + header.version = 6; + header.unityVersion = "5.x.x"; + header.unityRevision = "2017.4.18f1"; + } + else + { + reader.Position -= 4; + goto default; + } + } + else + { + header.version = reader.ReadUInt32(); + header.unityVersion = reader.ReadStringToNull(); + header.unityRevision = reader.ReadStringToNull(); + } + break; + case "ENCR": + header.version = 6; // is 7 but does not have uncompressedDataHash + header.unityVersion = "5.x.x"; + header.unityRevision = "2019.4.32f1"; + break; + default: + if (Game.Type.IsNaraka()) + { + header.signature = "UnityFS"; + goto case "UnityFS"; + } + break; + + } + + return header; + } + private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader) { if (m_Header.version >= 4) @@ -221,12 +243,12 @@ namespace AssetStudio public void ReadFiles(Stream blocksStream, string path) { - FileList = new StreamFile[m_DirectoryInfo.Length]; + fileList = new StreamFile[m_DirectoryInfo.Length]; for (int i = 0; i < m_DirectoryInfo.Length; i++) { var node = m_DirectoryInfo[i]; var file = new StreamFile(); - FileList[i] = file; + fileList[i] = file; file.path = node.path; file.fileName = Path.GetFileName(node.path); if (node.size >= int.MaxValue) @@ -247,42 +269,74 @@ namespace AssetStudio } } - private void DecryptHeader(int key) + private void DecryptHeader() { - var rand = new XORShift128(); - rand.InitSeed(key); - m_Header.flags ^= (ArchiveFlags)rand.NextDecryptInt(); - m_Header.size ^= rand.NextDecryptLong(); - m_Header.uncompressedBlocksInfoSize ^= rand.NextDecryptUInt(); - m_Header.compressedBlocksInfoSize ^= rand.NextDecryptUInt(); + m_Header.flags ^= (ArchiveFlags)XORShift128.NextDecryptInt(); + m_Header.size ^= XORShift128.NextDecryptLong(); + m_Header.uncompressedBlocksInfoSize ^= XORShift128.NextDecryptUInt(); + m_Header.compressedBlocksInfoSize ^= XORShift128.NextDecryptUInt(); + XORShift128.Init = false; } private void ReadHeader(EndianBinaryReader reader) { - if (reader.Game.Name == "BH3") + if (Game.Type.IsBH3() && XORShift128.Init) { - var key = reader.ReadInt32(); m_Header.flags = (ArchiveFlags)reader.ReadUInt32(); m_Header.size = reader.ReadInt64(); m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); - DecryptHeader(key); + DecryptHeader(); + var encUnityVersion = reader.ReadStringToNull(); var encUnityRevision = reader.ReadStringToNull(); + return; } - else + + m_Header.size = reader.ReadInt64(); + m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); + m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); + m_Header.flags = (ArchiveFlags)reader.ReadUInt32(); + if (m_Header.signature != "UnityFS" && !Game.Type.IsSRGroup()) { - m_Header.size = reader.ReadInt64(); - m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); - m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); - m_Header.flags = (ArchiveFlags)reader.ReadUInt32(); + reader.ReadByte(); + } + + if (Game.Type.IsNaraka()) + { + m_Header.compressedBlocksInfoSize -= 0xCA; + m_Header.uncompressedBlocksInfoSize -= 0xCA; } } private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader) { + if (Game.Type.IsCNUnity()) + { + ArchiveFlags mask; + + var version = ParseVersion(); + //Flag changed it in these versions + if (version[0] < 2020 || //2020 and earlier + (version[0] == 2020 && version[1] == 3 && version[2] <= 34) || //2020.3.34 and earlier + (version[0] == 2021 && version[1] == 3 && version[2] <= 2) || //2021.3.2 and earlier + (version[0] == 2022 && version[1] == 3 && version[2] <= 1)) //2022.3.1 and earlier + { + mask = ArchiveFlags.BlockInfoNeedPaddingAtStart; + } + else + { + mask = ArchiveFlags.CNUnityEncryption; + } + + if ((m_Header.flags & mask) != 0) + { + CNUnity = new CNUnity(reader); + } + } + byte[] blocksInfoBytes; - if (m_Header.version >= 7 && reader.Game.Name != "SR_CB2" && reader.Game.Name != "SR_CB3") + if (m_Header.version >= 7 && !Game.Type.IsSRGroup()) { reader.AlignStream(16); } @@ -298,6 +352,7 @@ namespace AssetStudio blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); } MemoryStream blocksInfoUncompresseddStream; + var blocksInfoBytesSpan = blocksInfoBytes.AsSpan(); var uncompressedSize = m_Header.uncompressedBlocksInfoSize; var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask); switch (compressionType) //kArchiveCompressionTypeMask @@ -321,7 +376,7 @@ namespace AssetStudio case CompressionType.Lz4HC: //LZ4HC { var uncompressedBytes = new byte[uncompressedSize]; - var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes); + var numWrite = LZ4Codec.Decode(blocksInfoBytesSpan, uncompressedBytes); if (numWrite != uncompressedSize) { throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); @@ -330,10 +385,9 @@ namespace AssetStudio break; } case CompressionType.Lz4Mr0k: //Lz4Mr0k - var blocksInfoSize = blocksInfoBytes.Length; - if (Mr0k.IsMr0k(blocksInfoBytes)) + if (Mr0kUtils.IsMr0k(blocksInfoBytesSpan)) { - Mr0k.Decrypt(ref blocksInfoBytes, ref blocksInfoSize); + blocksInfoBytesSpan = Mr0kUtils.Decrypt(blocksInfoBytesSpan, (Mr0k)Game).ToArray(); } goto case CompressionType.Lz4HC; default: @@ -341,7 +395,7 @@ namespace AssetStudio } using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) { - if ((reader.Game.Name != "SR_CB2" && reader.Game.Name != "SR_CB3") || m_Header.signature != "ENCR") + if (m_Header.version >= 7 || !Game.Type.IsSRGroup()) { var uncompressedDataHash = blocksInfoReader.ReadBytes(16); } @@ -370,12 +424,17 @@ namespace AssetStudio }; } } + if (!Game.Type.IsCNUnity() && (m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0) + { + reader.AlignStream(16); + } } private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) { - foreach (var blockInfo in m_BlocksInfo) + for (int i = 0; i < m_BlocksInfo.Length; i++) { + var blockInfo = m_BlocksInfo[i]; var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask); switch (compressionType) //kStorageBlockCompressionTypeMask { @@ -394,20 +453,28 @@ namespace AssetStudio case CompressionType.Lz4Mr0k: //Lz4Mr0k { var compressedSize = (int)blockInfo.compressedSize; - var compressedBytes = new byte[compressedSize]; + var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); reader.Read(compressedBytes, 0, compressedSize); - if (compressionType == CompressionType.Lz4Mr0k && Mr0k.IsMr0k(compressedBytes)) + var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize); + if (compressionType == CompressionType.Lz4Mr0k && Mr0kUtils.IsMr0k(compressedBytes)) { - Mr0k.Decrypt(ref compressedBytes, ref compressedSize); + compressedBytesSpan = Mr0kUtils.Decrypt(compressedBytesSpan, (Mr0k)Game); + } + if (Game.Type.IsCNUnity() && (blockInfo.flags & StorageBlockFlags.CNUnity) != 0) + { + CNUnity.DecryptBlock(compressedBytesSpan, compressedSize, i); } var uncompressedSize = (int)blockInfo.uncompressedSize; - var uncompressedBytes = new byte[uncompressedSize]; - var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize); + var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize); + var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize); + var numWrite = LZ4Codec.Decode(compressedBytesSpan, uncompressedBytesSpan); if (numWrite != uncompressedSize) { throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); } blocksStream.Write(uncompressedBytes, 0, uncompressedSize); + BigArrayPool.Shared.Return(compressedBytes); + BigArrayPool.Shared.Return(uncompressedBytes); break; } default: @@ -416,5 +483,11 @@ namespace AssetStudio } blocksStream.Position = 0; } + + public int[] ParseVersion() + { + var versionSplit = Regex.Replace(m_Header.unityRevision, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); + return versionSplit.Select(int.Parse).ToArray(); + } } } diff --git a/AssetStudio/CABManager.cs b/AssetStudio/CABManager.cs deleted file mode 100644 index 8b21de6..0000000 --- a/AssetStudio/CABManager.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -namespace AssetStudio -{ - public static class CABManager - { - public static Dictionary CABMap = new Dictionary(StringComparer.OrdinalIgnoreCase); - public static Dictionary> offsets = new Dictionary>(); - - public static void BuildMap(List files, Game game) - { - Logger.Info($"Building {game.Name}Map"); - try - { - int collisions = 0; - CABMap.Clear(); - Progress.Reset(); - for (int i = 0; i < files.Count; i++) - { - var file = files[i]; - var reader = new FileReader(file, game); - var gameFile = new GameFile(reader); - reader.Dispose(); - foreach (var bundle in gameFile.Bundles) - { - foreach (var cab in bundle.Value) - { - var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), cab.fileName); - using (var cabReader = new FileReader(dummyPath, cab.stream)) - { - if (cabReader.FileType == FileType.AssetsFile) - { - if (CABMap.ContainsKey(cab.path)) - { - collisions++; - continue; - } - var assetsFile = new SerializedFile(cabReader, null, reader.FullPath); - var dependencies = assetsFile.m_Externals.Select(x => x.fileName).ToList(); - CABMap.Add(cab.path, new Entry(file, bundle.Key, dependencies)); - } - } - } - } - Logger.Info($"[{i + 1}/{files.Count}] Processed {Path.GetFileName(file)}"); - Progress.Report(i + 1, files.Count); - } - - CABMap = CABMap.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value); - var outputFile = new FileInfo($"Maps/{game.Name}Map.bin"); - - if (!outputFile.Directory.Exists) - outputFile.Directory.Create(); - - using (var binaryFile = outputFile.Create()) - using (var writer = new BinaryWriter(binaryFile)) - { - writer.Write(CABMap.Count); - foreach (var cab in CABMap) - { - writer.Write(cab.Key); - writer.Write(cab.Value.Path); - writer.Write(cab.Value.Offset); - writer.Write(cab.Value.Dependencies.Count); - foreach (var dependancy in cab.Value.Dependencies) - { - writer.Write(dependancy); - } - } - } - Logger.Info($"{game.Name}Map build successfully, {collisions} collisions found !!"); - } - catch (Exception e) - { - Logger.Warning($"{game.Name}Map was not build, {e.Message}"); - } - } - public static void LoadMap(Game game) - { - Logger.Info($"Loading {game.Name}Map"); - try - { - CABMap.Clear(); - using (var binaryFile = File.OpenRead($"Maps/{game.Name}Map.bin")) - using (var reader = new BinaryReader(binaryFile)) - { - var count = reader.ReadInt32(); - for (int i = 0; i < count; i++) - { - var cab = reader.ReadString(); - var path = reader.ReadString(); - var offset = reader.ReadInt64(); - var depCount = reader.ReadInt32(); - var dependencies = new List(); - for (int j = 0; j < depCount; j++) - { - var dependancy = reader.ReadString(); - dependencies.Add(dependancy); - } - CABMap.Add(cab, new Entry(path, offset, dependencies)); - } - } - Logger.Info($"Loaded {game.Name}Map !!"); - } - catch (Exception e) - { - Logger.Warning($"{game.Name}Map was not loaded, {e.Message}"); - } - } - - public static void AddCABOffsets(string[] path, List cabs) - { - for (int i = 0; i < cabs.Count; i++) - { - var cab = cabs[i]; - if (CABMap.TryGetValue(cab, out var entry)) - { - if (!path.Contains(entry.Path)) - { - if (!offsets.ContainsKey(entry.Path)) - { - offsets.Add(entry.Path, new HashSet()); - } - offsets[entry.Path].Add(entry.Offset); - } - foreach (var dep in entry.Dependencies) - { - if (!cabs.Contains(dep)) - cabs.Add(dep); - } - } - } - } - - public static bool FindCAB(string path, out List cabs) - { - cabs = CABMap.Where(x => x.Value.Path.Contains(path)).Select(x => x.Key).ToList(); - return cabs.Count != 0; - } - - public static string[] ProcessFiles(string[] files) - { - foreach (var file in files) - { - if (!offsets.ContainsKey(file)) - { - offsets.Add(file, new HashSet()); - } - if (FindCAB(file, out var cabs)) - { - AddCABOffsets(files, cabs); - } - } - return offsets.Keys.ToArray(); - } - - public static string[] ProcessDependencies(string[] files) - { - if (CABMap.Count == 0) - { - Logger.Warning("CABMap is not build, skip resolving dependencies..."); - } - else - { - Logger.Info("Resolving Dependencies..."); - var file = files.FirstOrDefault(); - var supportedExtensions = GameManager.GetGames().Select(x => x.Extension).ToList(); - if (supportedExtensions.Contains(Path.GetExtension(file))) - { - files = ProcessFiles(files); - } - } - return files; - } - } - - public class Entry : IComparable - { - public string Path; - public long Offset; - public List Dependencies; - public Entry(string path, long offset, List dependencies) - { - Path = path; - Offset = offset; - Dependencies = dependencies; - } - public int CompareTo(Entry other) - { - if (other == null) return 1; - - int result; - if (other == null) - throw new ArgumentException("Object is not an Entry"); - - result = Path.CompareTo(other.Path); - - if (result == 0) - result = Offset.CompareTo(other.Offset); - - return result; - } - } -} diff --git a/AssetStudio/Classes/Animation.cs b/AssetStudio/Classes/Animation.cs index d868a21..b03035b 100644 --- a/AssetStudio/Classes/Animation.cs +++ b/AssetStudio/Classes/Animation.cs @@ -19,17 +19,5 @@ namespace AssetStudio m_Animations[i] = new PPtr(reader); } } - - public bool IsContainsAnimationClip(AnimationClip clip) - { - foreach (PPtr ptr in m_Animations) - { - if (ptr.TryGet(out var animationClip) && animationClip.Equals(clip)) - { - return true; - } - } - return false; - } } } diff --git a/AssetStudio/Classes/AnimationClip.cs b/AssetStudio/Classes/AnimationClip.cs index 305e0a3..7549143 100644 --- a/AssetStudio/Classes/AnimationClip.cs +++ b/AssetStudio/Classes/AnimationClip.cs @@ -1,12 +1,12 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; -using System.Collections.Generic; +using System.Runtime.InteropServices; namespace AssetStudio { - public class Keyframe : IYAMLExportable - where T : struct, IYAMLExportable + public class Keyframe { public float time; public T value; @@ -15,7 +15,6 @@ namespace AssetStudio public int weightedMode; public T inWeight; public T outWeight; - public int tangentMode; public Keyframe(ObjectReader reader, Func readerFunc) @@ -31,46 +30,9 @@ namespace AssetStudio outWeight = readerFunc(); } } - - public Keyframe(float time, T value, T weight) : this(time, value, default, default, weight) - { - tangentMode = 0; - } - - public Keyframe(float time, T value, T inSlope, T outSlope, T weight) - { - this.time = time; - this.value = value; - this.inSlope = inSlope; - this.outSlope = outSlope; - weightedMode = 0; - inWeight = weight; - outWeight = weight; - tangentMode = 1; - } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.AddSerializedVersion(2); - node.Add(nameof(time), time); - node.Add(nameof(value), value.ExportYAML()); - node.Add(nameof(inSlope), inSlope.ExportYAML()); - node.Add(nameof(outSlope), outSlope.ExportYAML()); - node.Add(nameof(tangentMode), tangentMode); - node.Add(nameof(weightedMode), weightedMode); - node.Add(nameof(inWeight), inWeight.ExportYAML()); - node.Add(nameof(outWeight), outWeight.ExportYAML()); - return node; - } - - public static Float DefaultFloatWeight => 1.0f / 3.0f; - public static Vector3 DefaultVector3Weight => new Vector3(1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f); - public static Quaternion DefaultQuaternionWeight => new Quaternion(1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f); } - public class AnimationCurve : IYAMLExportable - where T : struct, IYAMLExportable + public class AnimationCurve { public Keyframe[] m_Curve; public int m_PreInfinity; @@ -94,40 +56,9 @@ namespace AssetStudio m_RotationOrder = reader.ReadInt32(); } } - - public AnimationCurve() - { - m_PreInfinity = 2; - m_PostInfinity = 2; - m_RotationOrder = 4; - m_Curve = Array.Empty>(); - } - - public AnimationCurve(List> keyframes) - { - m_PreInfinity = 2; - m_PostInfinity = 2; - m_RotationOrder = 4; - m_Curve = new Keyframe[keyframes.Count]; - for (int i = 0; i < keyframes.Count; i++) - { - m_Curve[i] = keyframes[i]; - } - } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.AddSerializedVersion(2); - node.Add(nameof(m_Curve), m_Curve.ExportYAML()); - node.Add(nameof(m_PreInfinity), m_PreInfinity); - node.Add(nameof(m_PostInfinity), m_PostInfinity); - node.Add(nameof(m_RotationOrder), m_RotationOrder); - return node; - } } - public class QuaternionCurve : IYAMLExportable + public class QuaternionCurve { public AnimationCurve curve; public string path; @@ -137,79 +68,9 @@ namespace AssetStudio curve = new AnimationCurve(reader, reader.ReadQuaternion); path = reader.ReadAlignedString(); } - - public QuaternionCurve(string path) - { - curve = new AnimationCurve(); - this.path = path; - } - - public QuaternionCurve(QuaternionCurve copy, List> keyframes) : this(copy.path, keyframes) { } - - public QuaternionCurve(string path, List> keyframes) - { - curve = new AnimationCurve(keyframes); - this.path = path; - } - - public YAMLNode ExportYAML() - { - YAMLMappingNode node = new YAMLMappingNode(); - node.Add(nameof(curve), curve.ExportYAML()); - node.Add(nameof(path), path); - return node; - } - - public override bool Equals(object obj) - { - if (obj is QuaternionCurve quaternionCurve) - { - return path == quaternionCurve.path; - } - return false; - } - - public override int GetHashCode() - { - int hash = 199; - unchecked - { - hash = 617 + hash * path.GetHashCode(); - } - return hash; - } } - public class ACLClip - { - public byte[] m_ClipData; - public uint[] m_ClipDataUint; - - public uint m_CurveCount; - public uint m_ConstCurveCount; - public ACLClip(ObjectReader reader) - { - if (reader.Game.Name == "SR_CB2" || reader.Game.Name == "SR_CB3") - { - m_ClipDataUint = reader.ReadUInt32Array(); - } - else - { - m_ClipData = reader.ReadUInt8Array(); - reader.AlignStream(); - } - - m_CurveCount = reader.ReadUInt32(); - - if (reader.Game.Name == "SR_CB2" || reader.Game.Name == "SR_CB3") - { - m_ConstCurveCount = reader.ReadUInt32(); - } - } - public bool IsSet => m_ClipDataUint != null && m_ClipDataUint.Length > 0 || m_ClipData != null && m_ClipData.Length > 0; - } - - public class PackedFloatVector : IYAMLExportable + public class PackedFloatVector { public uint m_NumItems; public float m_Range; @@ -231,17 +92,6 @@ namespace AssetStudio reader.AlignStream(); } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_NumItems), m_NumItems); - node.Add(nameof(m_Range), m_Range); - node.Add(nameof(m_Start), m_Start); - node.Add(nameof(m_Data), m_Data.ExportYAML()); - node.Add(nameof(m_BitSize), m_BitSize); - return node; - } - public float[] UnpackFloats(int itemCountInChunk, int chunkStride, int start = 0, int numChunks = -1) { int bitPos = m_BitSize * start; @@ -281,7 +131,7 @@ namespace AssetStudio } } - public class PackedIntVector : IYAMLExportable + public class PackedIntVector { public uint m_NumItems; public byte[] m_Data; @@ -299,15 +149,6 @@ namespace AssetStudio reader.AlignStream(); } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_NumItems), m_NumItems); - node.Add(nameof(m_Data), m_Data.ExportYAML()); - node.Add(nameof(m_BitSize), m_BitSize); - return node; - } - public int[] UnpackInts() { var data = new int[m_NumItems]; @@ -335,7 +176,7 @@ namespace AssetStudio } } - public class PackedQuatVector : IYAMLExportable + public class PackedQuatVector { public uint m_NumItems; public byte[] m_Data; @@ -350,14 +191,6 @@ namespace AssetStudio reader.AlignStream(); } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_NumItems), m_NumItems); - node.Add(nameof(m_Data), m_Data.ExportYAML()); - return node; - } - public Quaternion[] UnpackQuats() { var data = new Quaternion[m_NumItems]; @@ -423,7 +256,7 @@ namespace AssetStudio } } - public class CompressedAnimationCurve : IYAMLExportable + public class CompressedAnimationCurve { public string m_Path; public PackedIntVector m_Times; @@ -441,21 +274,9 @@ namespace AssetStudio m_PreInfinity = reader.ReadInt32(); m_PostInfinity = reader.ReadInt32(); } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_Path), m_Path); - node.Add(nameof(m_Times), m_Times.ExportYAML()); - node.Add(nameof(m_Values), m_Values.ExportYAML()); - node.Add(nameof(m_Slopes), m_Slopes.ExportYAML()); - node.Add(nameof(m_PreInfinity), m_PreInfinity); - node.Add(nameof(m_PostInfinity), m_PostInfinity); - return node; - } } - public class Vector3Curve : IYAMLExportable + public class Vector3Curve { public AnimationCurve curve; public string path; @@ -465,51 +286,11 @@ namespace AssetStudio curve = new AnimationCurve(reader, reader.ReadVector3); path = reader.ReadAlignedString(); } - - public Vector3Curve(Vector3Curve copy, List> keyframes) - : this(copy.path, keyframes) { } - public Vector3Curve(string path) - { - curve = new AnimationCurve(); - this.path = path; - } - public Vector3Curve(string path, List> keyframes) - { - curve = new AnimationCurve(keyframes); - this.path = path; - } - - public YAMLNode ExportYAML() - { - YAMLMappingNode node = new YAMLMappingNode(); - node.Add(nameof(curve), curve.ExportYAML()); - node.Add(nameof(path), path); - return node; - } - - public override bool Equals(object obj) - { - if (obj is Vector3Curve vector3Curve) - { - return path == vector3Curve.path; - } - return false; - } - - public override int GetHashCode() - { - int hash = 577; - unchecked - { - hash = 419 + hash * path.GetHashCode(); - } - return hash; - } } - public class FloatCurve : IYAMLExportable + public class FloatCurve { - public AnimationCurve curve; + public AnimationCurve curve; public string attribute; public string path; public ClassIDType classID; @@ -518,64 +299,15 @@ namespace AssetStudio public FloatCurve(ObjectReader reader) { - curve = new AnimationCurve(reader, reader.ReadFloat); + curve = new AnimationCurve(reader, reader.ReadSingle); attribute = reader.ReadAlignedString(); path = reader.ReadAlignedString(); classID = (ClassIDType)reader.ReadInt32(); script = new PPtr(reader); } - - public FloatCurve(FloatCurve copy, List> keyframes) : this(copy.path, copy.attribute, copy.classID, copy.script, keyframes) { } - public FloatCurve(string path, string attribute, ClassIDType classID, PPtr script) - { - curve = new AnimationCurve(); - this.attribute = attribute; - this.path = path; - this.classID = classID; - this.script = script; - } - public FloatCurve(string path, string attribute, ClassIDType classID, PPtr script, List> keyframes) - : this(path, attribute, classID, script) - { - curve = new AnimationCurve(keyframes); - this.attribute = attribute; - this.path = path; - this.classID = classID; - this.script = script; - } - - public YAMLNode ExportYAML() - { - YAMLMappingNode node = new YAMLMappingNode(); - node.Add(nameof(curve), curve.ExportYAML()); - node.Add(nameof(attribute), attribute); - node.Add(nameof(path), path); - node.Add(nameof(classID), (int)classID); - node.Add(nameof(script), script.ExportYAML()); - return node; - } - - public override bool Equals(object obj) - { - if (obj is FloatCurve floatCurve) - { - return attribute == floatCurve.attribute && path == floatCurve.path && classID == floatCurve.classID; - } - return false; - } - - public override int GetHashCode() - { - int hash = 17; - unchecked - { - hash = hash * 23 + path.GetHashCode(); - } - return hash; - } } - public class PPtrKeyframe : IYAMLExportable + public class PPtrKeyframe { public float time; public PPtr value; @@ -586,27 +318,14 @@ namespace AssetStudio time = reader.ReadSingle(); value = new PPtr(reader); } - public PPtrKeyframe(float time, PPtr script) - { - this.time = time; - value = script; - } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(time), time); - node.Add(nameof(value), value.ExportYAML()); - return node; - } } - public class PPtrCurve : IYAMLExportable + public class PPtrCurve { public PPtrKeyframe[] curve; public string attribute; public string path; - public ClassIDType classID; + public int classID; public PPtr script; @@ -621,63 +340,12 @@ namespace AssetStudio attribute = reader.ReadAlignedString(); path = reader.ReadAlignedString(); - classID = (ClassIDType)reader.ReadInt32(); + classID = reader.ReadInt32(); script = new PPtr(reader); } - - public PPtrCurve(PPtrCurve copy, List keyframes) : this(copy.path, copy.attribute, copy.classID, copy.script, keyframes) { } - public PPtrCurve(string path, string attribute, ClassIDType classID, PPtr script) - { - this.attribute = attribute; - this.path = path; - this.classID = classID; - this.script = script; - } - public PPtrCurve(string path, string attribute, ClassIDType classID, PPtr script, IReadOnlyList keyframes) : - this(path, attribute, classID, script) - { - curve = new PPtrKeyframe[keyframes.Count]; - for (int i = 0; i < keyframes.Count; i++) - { - curve[i] = keyframes[i]; - } - } - - public YAMLNode ExportYAML() - { - YAMLMappingNode node = new YAMLMappingNode(); - node.Add(nameof(curve), curve.ExportYAML()); - node.Add(nameof(attribute), attribute); - node.Add(nameof(path), path); - node.Add(nameof(classID), ((int)classID).ToString()); - node.Add(nameof(script), script.ExportYAML()); - return node; - } - - public override bool Equals(object obj) - { - if (obj is PPtrCurve pptrCurve) - { - return this == pptrCurve; - } - return false; - } - - public override int GetHashCode() - { - int hash = 113; - unchecked - { - hash = hash + 457 * attribute.GetHashCode(); - hash = hash * 433 + path.GetHashCode(); - hash = hash * 223 + classID.GetHashCode(); - hash = hash * 911 + script.GetHashCode(); - } - return hash; - } } - public class AABB : IYAMLExportable + public class AABB { public Vector3 m_Center; public Vector3 m_Extent; @@ -687,14 +355,6 @@ namespace AssetStudio m_Center = reader.ReadVector3(); m_Extent = reader.ReadVector3(); } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_Center), m_Center.ExportYAML()); - node.Add(nameof(m_Extent), m_Extent.ExportYAML()); - return node; - } } public class xform @@ -796,6 +456,33 @@ namespace AssetStudio } } + public class ACLClip + { + public byte[] m_ClipData; + + public uint m_CurveCount; + public uint m_ConstCurveCount; + public ACLClip(ObjectReader reader) + { + var byteCount = reader.ReadInt32(); + + if (reader.Game.Type.IsSRGroup()) + { + byteCount *= 4; + } + + m_ClipData = reader.ReadBytes(byteCount); + reader.AlignStream(); + + m_CurveCount = reader.ReadUInt32(); + + if (reader.Game.Type.IsSRGroup()) + { + m_ConstCurveCount = reader.ReadUInt32(); + } + } + } + public class StreamedClip { public uint[] data; @@ -816,7 +503,7 @@ namespace AssetStudio public float outSlope; public float inSlope; - public StreamedCurveKey(BinaryReader reader) + public StreamedCurveKey(EndianBinaryReader reader) { index = reader.ReadInt32(); coeff = reader.ReadSingleArray(4); @@ -847,7 +534,7 @@ namespace AssetStudio public float time; public StreamedCurveKey[] keyList; - public StreamedFrame(BinaryReader reader) + public StreamedFrame(EndianBinaryReader reader) { time = reader.ReadSingle(); @@ -865,7 +552,7 @@ namespace AssetStudio var frameList = new List(); var buffer = new byte[data.Length * 4]; Buffer.BlockCopy(data, 0, buffer, 0, buffer.Length); - using (var reader = new BinaryReader(new MemoryStream(buffer))) + using (var reader = new EndianBinaryReader(new MemoryStream(buffer), EndianType.LittleEndian)) { while (reader.BaseStream.Position < reader.BaseStream.Length) { @@ -959,10 +646,10 @@ namespace AssetStudio public class Clip { + public ACLClip m_ACLClip; public StreamedClip m_StreamedClip; public DenseClip m_DenseClip; public ConstantClip m_ConstantClip; - public ACLClip m_ACLClip; public ValueArrayConstant m_Binding; public Clip(ObjectReader reader) @@ -970,7 +657,7 @@ namespace AssetStudio var version = reader.version; m_StreamedClip = new StreamedClip(reader); m_DenseClip = new DenseClip(reader); - if (reader.Game.Name == "SR_CB2" || reader.Game.Name == "SR_CB3") + if (reader.Game.Type.IsSRGroup()) { m_ACLClip = new ACLClip(reader); } @@ -978,7 +665,7 @@ namespace AssetStudio { m_ConstantClip = new ConstantClip(reader); } - if (reader.Game.Name != "SR_CB2" && reader.Game.Name != "SR_CB3" && reader.Game.Name != "TOT") + if (reader.Game.Type.IsGIGroup() || reader.Game.Type.IsBH3() || reader.Game.Type.IsZZZCB1()) { m_ACLClip = new ACLClip(reader); } @@ -1045,7 +732,7 @@ namespace AssetStudio } } - public class ClipMuscleConstant : IYAMLExportable + public class ClipMuscleConstant { public HumanPose m_DeltaPose; public xform m_StartX; @@ -1137,45 +824,23 @@ namespace AssetStudio m_HeightFromFeet = reader.ReadBoolean(); reader.AlignStream(); } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.AddSerializedVersion(2); - node.Add(nameof(m_StartTime), m_StartTime); - node.Add(nameof(m_StopTime), m_StopTime); - node.Add(nameof(m_OrientationOffsetY), m_OrientationOffsetY); - node.Add(nameof(m_Level), m_Level); - node.Add(nameof(m_CycleOffset), m_CycleOffset); - node.Add(nameof(m_LoopTime), m_LoopTime); - node.Add(nameof(m_LoopBlend), m_LoopBlend); - node.Add(nameof(m_LoopBlendOrientation), m_LoopBlendOrientation); - node.Add(nameof(m_LoopBlendPositionY), m_LoopBlendPositionY); - node.Add(nameof(m_LoopBlendPositionXZ), m_LoopBlendPositionXZ); - node.Add(nameof(m_KeepOriginalOrientation), m_KeepOriginalOrientation); - node.Add(nameof(m_KeepOriginalPositionY), m_KeepOriginalPositionY); - node.Add(nameof(m_KeepOriginalPositionXZ), m_KeepOriginalPositionXZ); - node.Add(nameof(m_HeightFromFeet), m_HeightFromFeet); - node.Add(nameof(m_Mirror), m_Mirror); - return node; - } } - public class GenericBinding : IYAMLExportable + public class GenericBinding { - public int[] version; public uint path; public uint attribute; public PPtr script; public ClassIDType typeID; public byte customType; public byte isPPtrCurve; - + public byte isIntCurve; + public GenericBinding() { } public GenericBinding(ObjectReader reader) { - version = reader.version; + var version = reader.version; path = reader.ReadUInt32(); attribute = reader.ReadUInt32(); script = new PPtr(reader); @@ -1189,24 +854,15 @@ namespace AssetStudio } customType = reader.ReadByte(); isPPtrCurve = reader.ReadByte(); + if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up + { + isIntCurve = reader.ReadByte(); + } reader.AlignStream(); } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(path), path); - node.Add(nameof(attribute), attribute); - node.Add(nameof(script), script.ExportYAML()); - node.Add("classID", ((int)typeID).ToString()); - node.Add(nameof(customType), ((int)customType).ToString()); - node.Add(nameof(isPPtrCurve), isPPtrCurve); - return node; - } - - public int GetDimension() => attribute == 2 ? 4 : 3; } - public class AnimationClipBindingConstant : IYAMLExportable + + public class AnimationClipBindingConstant { public GenericBinding[] genericBindings; public PPtr[] pptrCurveMapping; @@ -1230,14 +886,6 @@ namespace AssetStudio } } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(genericBindings), genericBindings.ExportYAML()); - node.Add(nameof(pptrCurveMapping), pptrCurveMapping.ExportYAML()); - return node; - } - public GenericBinding FindBinding(int index) { int curves = 0; @@ -1274,7 +922,7 @@ namespace AssetStudio } } - public class AnimationEvent : IYAMLExportable + public class AnimationEvent { public float time; public string functionName; @@ -1299,19 +947,6 @@ namespace AssetStudio } messageOptions = reader.ReadInt32(); } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(time), time); - node.Add(nameof(functionName), functionName); - node.Add(nameof(data), data); - node.Add(nameof(objectReferenceParameter), objectReferenceParameter.ExportYAML()); - node.Add(nameof(floatParameter), floatParameter); - node.Add(nameof(intParameter), intParameter); - node.Add(nameof(messageOptions), messageOptions); - return node; - } } public enum AnimationType @@ -1321,7 +956,7 @@ namespace AssetStudio Humanoid = 3 }; - public sealed class AnimationClip : NamedObject, IYAMLExportable + public sealed class AnimationClip : NamedObject { public AnimationType m_AnimationType; public bool m_Legacy; @@ -1339,9 +974,6 @@ namespace AssetStudio public AABB m_Bounds; public uint m_MuscleClipSize; public ClipMuscleConstant m_MuscleClip; - public byte[] m_AclClipData; - public GenericBinding[] m_AclBindings; - public KeyValuePair m_AclRange; public AnimationClipBindingConstant m_ClipBindingConstant; public AnimationEvent[] m_Events; @@ -1363,10 +995,6 @@ namespace AssetStudio m_Legacy = true; } m_Compressed = reader.ReadBoolean(); - if (m_Compressed && reader.Game.Name != "ToT") - { - m_Compressed = false; - } if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up { m_UseHighQualityCurve = reader.ReadBoolean(); @@ -1438,19 +1066,19 @@ namespace AssetStudio m_MuscleClipSize = reader.ReadUInt32(); m_MuscleClip = new ClipMuscleConstant(reader); } + if (reader.Game.Type.IsSRGroup()) + { + var m_AclClipData = reader.ReadUInt8Array(); + var aclBindingsCount = reader.ReadInt32(); + var m_AclBindings = new GenericBinding[aclBindingsCount]; + for (int i = 0; i < aclBindingsCount; i++) + { + m_AclBindings[i] = new GenericBinding(reader); + } + var m_AclRange = new KeyValuePair(reader.ReadSingle(), reader.ReadSingle()); + } if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up { - if (reader.Game.Name == "SR_CB2" || reader.Game.Name == "SR_CB3") - { - m_AclClipData = reader.ReadUInt8Array(); - var aclBindingsCount = reader.ReadInt32(); - m_AclBindings = new GenericBinding[aclBindingsCount]; - for (int i = 0; i < aclBindingsCount; i++) - { - m_AclBindings[i] = new GenericBinding(reader); - } - m_AclRange = new KeyValuePair(reader.ReadSingle(), reader.ReadSingle()); - } m_ClipBindingConstant = new AnimationClipBindingConstant(reader); } if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up @@ -1470,158 +1098,5 @@ namespace AssetStudio reader.AlignStream(); } } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Add(nameof(m_Name), m_Name); - node.AddSerializedVersion(6); - node.Add(nameof(m_Legacy), m_Legacy); - node.Add(nameof(m_Compressed), m_Compressed); - node.Add(nameof(m_UseHighQualityCurve), m_UseHighQualityCurve); - node.Add(nameof(m_RotationCurves), m_RotationCurves.ExportYAML()); - node.Add(nameof(m_CompressedRotationCurves), m_CompressedRotationCurves.ExportYAML()); - node.Add(nameof(m_EulerCurves), m_EulerCurves.ExportYAML()); - node.Add(nameof(m_PositionCurves), m_PositionCurves.ExportYAML()); - node.Add(nameof(m_ScaleCurves), m_ScaleCurves.ExportYAML()); - node.Add(nameof(m_FloatCurves), m_FloatCurves.ExportYAML()); - node.Add(nameof(m_PPtrCurves), m_PPtrCurves.ExportYAML()); - node.Add(nameof(m_SampleRate), m_SampleRate); - node.Add(nameof(m_WrapMode), m_WrapMode); - node.Add(nameof(m_Bounds), m_Bounds.ExportYAML()); - node.Add(nameof(m_ClipBindingConstant), m_ClipBindingConstant.ExportYAML()); - node.Add("m_AnimationClipSettings", m_MuscleClip.ExportYAML()); - node.Add(nameof(m_Events), m_Events.ExportYAML()); - return node; - } - - public Dictionary FindTOS() - { - var tos = new Dictionary() { { 0, string.Empty } }; - foreach (var asset in assetsFile.assetsManager.assetsFileList.SelectMany(x => x.Objects).OrderBy(x => x.type).ToArray()) - { - switch (asset.type) - { - case ClassIDType.Avatar: - var avatar = asset as Avatar; - if (AddAvatarTOS(avatar, tos)) - { - return tos; - } - break; - case ClassIDType.Animator: - var animator = asset as Animator; - if (IsAnimatorContainsClip(animator)) - { - if (AddAnimatorTOS(animator, tos)) - { - return tos; - } - } - break; - case ClassIDType.Animation: - var animation = asset as Animation; - if (IsAnimationContainsClip(animation)) - { - if (AddAnimationTOS(animation, tos)) - { - return tos; - } - } - break; - } - } - return tos; - } - public IEnumerable FindRoots() - { - foreach (var asset in assetsFile.assetsManager.assetsFileList.SelectMany(x => x.Objects)) - { - switch (asset.type) - { - case ClassIDType.Animator: - Animator animator = (Animator)asset; - if (IsAnimatorContainsClip(animator)) - { - if (animator.m_GameObject.TryGet(out var go)) - { - yield return go; - } - } - break; - - case ClassIDType.Animation: - Animation animation = (Animation)asset; - if (IsAnimationContainsClip(animation)) - { - if (animation.m_GameObject.TryGet(out var go)) - { - yield return go; - } - } - break; - } - } - - yield break; - } - private bool IsAnimatorContainsClip(Animator animator) - { - if (animator.m_Controller.TryGet(out var runtime)) - { - return runtime.IsContainsAnimationClip(this); - } - else - { - return false; - } - } - private bool IsAnimationContainsClip(Animation animation) - { - return animation.IsContainsAnimationClip(this); - } - private bool AddAvatarTOS(Avatar avatar, Dictionary tos) - { - return AddTOS(avatar.m_TOS.ToDictionary(x => x.Key, x => x.Value), tos); - } - private bool AddAnimatorTOS(Animator animator, Dictionary tos) - { - if (animator.m_Avatar.TryGet(out var avatar)) - { - if (AddAvatarTOS(avatar, tos)) - { - return true; - } - } - - Dictionary animatorTOS = animator.BuildTOS(); - return AddTOS(animatorTOS, tos); - } - private bool AddAnimationTOS(Animation animation, Dictionary tos) - { - if (animation.m_GameObject.TryGet(out var go)) - { - Dictionary animationTOS = go.BuildTOS(); - return AddTOS(animationTOS, tos); - } - return false; - } - private bool AddTOS(Dictionary src, Dictionary dest) - { - int tosCount = m_ClipBindingConstant.genericBindings.Length; - for (int i = 0; i < tosCount; i++) - { - ref GenericBinding binding = ref m_ClipBindingConstant.genericBindings[i]; - if (src.TryGetValue(binding.path, out string path)) - { - dest[binding.path] = path; - if (dest.Count == tosCount) - { - return true; - } - } - } - return false; - } } } diff --git a/AssetStudio/Classes/Animator.cs b/AssetStudio/Classes/Animator.cs index 34bd42c..a36bf1e 100644 --- a/AssetStudio/Classes/Animator.cs +++ b/AssetStudio/Classes/Animator.cs @@ -15,7 +15,7 @@ namespace AssetStudio { m_Avatar = new PPtr(reader); m_Controller = new PPtr(reader); - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + if (reader.Game.Type.IsGISubGroup()) { var m_FBIKAvatar = new PPtr(reader); //FBIKAvatar placeholder } @@ -67,31 +67,5 @@ namespace AssetStudio reader.AlignStream(); } } - - public Dictionary BuildTOS() - { - if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) - { - if (m_HasTransformHierarchy) - { - if (m_GameObject.TryGet(out var go)) - { - return go.BuildTOS(); - } - } - else - { - return new Dictionary() { { 0, string.Empty } }; - } - } - else - { - if (m_GameObject.TryGet(out var go)) - { - return go.BuildTOS(); - } - } - return null; - } } } diff --git a/AssetStudio/Classes/AnimatorController.cs b/AssetStudio/Classes/AnimatorController.cs index 905b13c..296456f 100644 --- a/AssetStudio/Classes/AnimatorController.cs +++ b/AssetStudio/Classes/AnimatorController.cs @@ -580,6 +580,7 @@ namespace AssetStudio public sealed class AnimatorController : RuntimeAnimatorController { + public Dictionary m_TOS; public PPtr[] m_AnimationClips; public AnimatorController(ObjectReader reader) : base(reader) @@ -588,7 +589,7 @@ namespace AssetStudio var m_Controller = new ControllerConstant(reader); int tosSize = reader.ReadInt32(); - var m_TOS = new Dictionary(tosSize); + m_TOS = new Dictionary(tosSize); for (int i = 0; i < tosSize; i++) { m_TOS.Add(reader.ReadUInt32(), reader.ReadAlignedString()); @@ -601,17 +602,5 @@ namespace AssetStudio m_AnimationClips[i] = new PPtr(reader); } } - - public override bool IsContainsAnimationClip(AnimationClip clip) - { - foreach (PPtr ptr in m_AnimationClips) - { - if (ptr.TryGet(out var animationClip) && animationClip.Equals(clip)) - { - return true; - } - } - return false; - } } } diff --git a/AssetStudio/Classes/AnimatorOverrideController.cs b/AssetStudio/Classes/AnimatorOverrideController.cs index 1602a74..c89e7a2 100644 --- a/AssetStudio/Classes/AnimatorOverrideController.cs +++ b/AssetStudio/Classes/AnimatorOverrideController.cs @@ -33,26 +33,5 @@ namespace AssetStudio m_Clips[i] = new AnimationClipOverride(reader); } } - - public override bool IsContainsAnimationClip(AnimationClip clip) - { - AnimationClip animationClip; - foreach (AnimationClipOverride overClip in m_Clips) - { - if (overClip.m_OriginalClip.TryGet(out animationClip) && animationClip.Equals(clip)) - { - return true; - } - else if (overClip.m_OverrideClip.TryGet(out animationClip) && animationClip.Equals(clip)) - { - return true; - } - } - if (m_Controller.TryGet(out var baseController)) - { - return baseController.IsContainsAnimationClip(clip); - } - return false; - } } } diff --git a/AssetStudio/Classes/AssetBundle.cs b/AssetStudio/Classes/AssetBundle.cs index b7e6b78..247575c 100644 --- a/AssetStudio/Classes/AssetBundle.cs +++ b/AssetStudio/Classes/AssetBundle.cs @@ -1,5 +1,8 @@ -using Newtonsoft.Json; +using System; +using System.Buffers.Binary; using System.Collections.Generic; +using System.Linq; +using System.Text; namespace AssetStudio { @@ -19,76 +22,64 @@ namespace AssetStudio public sealed class AssetBundle : NamedObject { - public static bool Exportable; - - public PPtr[] PreloadTable; - public KeyValuePair[] Container; - public AssetInfo MainAsset; - public uint RuntimeComaptability; - public string AssetBundleName; - public int DependencyCount; - public string[] Dependencies; - public bool IsStreamedScenessetBundle; - public int ExplicitDataLayout; - public int PathFlags; - public int SceneHashCount; - public KeyValuePair[] SceneHashes; + public PPtr[] m_PreloadTable; + public KeyValuePair[] m_Container; + //public AssetInfo m_MainAsset; + //public uint m_RuntimeComaptability; + //public string m_AssetBundleName; + //public string[] m_Dependencies; + //public bool m_IsStreamedSceneAssetBundle; + //public int m_ExplicitDataLayout; + //public int m_PathFlags; + //public KeyValuePair[] m_SceneHashes; public AssetBundle(ObjectReader reader) : base(reader) { var m_PreloadTableSize = reader.ReadInt32(); - PreloadTable = new PPtr[m_PreloadTableSize]; + m_PreloadTable = new PPtr[m_PreloadTableSize]; for (int i = 0; i < m_PreloadTableSize; i++) { - PreloadTable[i] = new PPtr(reader); + m_PreloadTable[i] = new PPtr(reader); } var m_ContainerSize = reader.ReadInt32(); - Container = new KeyValuePair[m_ContainerSize]; + m_Container = new KeyValuePair[m_ContainerSize]; for (int i = 0; i < m_ContainerSize; i++) { - Container[i] = new KeyValuePair(reader.ReadAlignedString(), new AssetInfo(reader)); + m_Container[i] = new KeyValuePair(reader.ReadAlignedString(), new AssetInfo(reader)); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") - { - MainAsset = new AssetInfo(reader); - RuntimeComaptability = reader.ReadUInt32(); - } - - AssetBundleName = reader.ReadAlignedString(); - DependencyCount = reader.ReadInt32(); - Dependencies = new string[DependencyCount]; - for (int k = 0; k < DependencyCount; k++) - { - Dependencies[k] = reader.ReadAlignedString(); - } - if (reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2") - { - IsStreamedScenessetBundle = reader.ReadBoolean(); - reader.AlignStream(); - PathFlags = reader.ReadInt32(); - } - else if (reader.Game.Name == "GI_CB3") - { - IsStreamedScenessetBundle = reader.ReadBoolean(); - reader.AlignStream(); - ExplicitDataLayout = reader.ReadInt32(); - PathFlags = reader.ReadInt32(); - } - else if (reader.Game.Name == "GI") - { - IsStreamedScenessetBundle = reader.ReadBoolean(); - reader.AlignStream(); - ExplicitDataLayout = reader.ReadInt32(); - PathFlags = reader.ReadInt32(); - SceneHashCount = reader.ReadInt32(); - SceneHashes = new KeyValuePair[SceneHashCount]; - for (int l = 0; l < SceneHashCount; l++) - { - SceneHashes[l] = new KeyValuePair(reader.ReadAlignedString(), reader.ReadAlignedString()); - } - } + //if (reader.Game.Type.IsMhyGroup()) + //{ + // m_MainAsset = new AssetInfo(reader); + // m_RuntimeComaptability = reader.ReadUInt32(); + // m_AssetBundleName = reader.ReadAlignedString(); + // var dependencyCount = reader.ReadInt32(); + // m_Dependencies = new string[dependencyCount]; + // for (int k = 0; k < dependencyCount; k++) + // { + // m_Dependencies[k] = reader.ReadAlignedString(); + // } + // if (reader.Game.Type.IsGIGroup()) + // { + // m_IsStreamedSceneAssetBundle = reader.ReadBoolean(); + // reader.AlignStream(); + // if (reader.Game.Type.IsGICB3() || reader.Game.Type.IsGI()) + // { + // m_ExplicitDataLayout = reader.ReadInt32(); + // } + // m_PathFlags = reader.ReadInt32(); + // if (reader.Game.Type.IsGI()) + // { + // var sceneHashCount = reader.ReadInt32(); + // m_SceneHashes = new KeyValuePair[sceneHashCount]; + // for (int l = 0; l < sceneHashCount; l++) + // { + // m_SceneHashes[l] = new KeyValuePair(reader.ReadAlignedString(), reader.ReadAlignedString()); + // } + // } + // } + //} } } } diff --git a/AssetStudio/Classes/GameObject.cs b/AssetStudio/Classes/GameObject.cs index a20baf0..d129beb 100644 --- a/AssetStudio/Classes/GameObject.cs +++ b/AssetStudio/Classes/GameObject.cs @@ -1,5 +1,4 @@ -using SevenZip; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,8 +9,6 @@ namespace AssetStudio { public PPtr[] m_Components; public string m_Name; - public uint m_Tag; - public bool m_IsActive; public Transform m_Transform; public MeshRenderer m_MeshRenderer; @@ -35,67 +32,6 @@ namespace AssetStudio var m_Layer = reader.ReadInt32(); m_Name = reader.ReadAlignedString(); - m_Tag = reader.ReadUInt16(); - m_IsActive = reader.ReadBoolean(); - } - public Transform GetTransform() - { - foreach (PPtr ptr in FetchComponents()) - { - if (!ptr.TryGet(out var comp)) - { - continue; - } - - if (comp.type == ClassIDType.Transform) - { - return comp as Transform; - } - } - throw new Exception("Can't find transform component"); - } - - private List> FetchComponents() - { - return m_Components.ToList(); - } - - public T FindComponent() - where T : Component - { - foreach (PPtr ptr in FetchComponents()) - { - // component could has not impelemented asset type - if (ptr.TryGet(out var comp) && comp is T t) - { - return t; - } - } - return null; - } - - public Dictionary BuildTOS() - { - Dictionary tos = new Dictionary() { { 0, string.Empty } }; - BuildTOS(this, string.Empty, tos); - return tos; - } - private void BuildTOS(GameObject parent, string parentPath, Dictionary tos) - { - Transform transform = parent.GetTransform(); - foreach (PPtr childPtr in transform.m_Children) - { - if (childPtr.TryGet(out var childTransform)) - { - if (childTransform.m_GameObject.TryGet(out var child)) - { - string path = parentPath != string.Empty ? parentPath + '/' + child.m_Name : child.m_Name; - var pathHash = CRC.CalculateDigestUTF8(path); - tos[pathHash] = path; - BuildTOS(child, path, tos); - } - } - } } } } diff --git a/AssetStudio/Classes/IndexObject.cs b/AssetStudio/Classes/IndexObject.cs index b94ed6b..b5adb56 100644 --- a/AssetStudio/Classes/IndexObject.cs +++ b/AssetStudio/Classes/IndexObject.cs @@ -1,5 +1,4 @@ -using Newtonsoft.Json; -using System.Collections.Generic; +using System.Collections.Generic; namespace AssetStudio { @@ -10,7 +9,6 @@ namespace AssetStudio public Index(ObjectReader reader) { - Object = new PPtr(reader); Size = reader.ReadUInt64(); } @@ -18,25 +16,16 @@ namespace AssetStudio public sealed class IndexObject : NamedObject { - public static bool Exportable; - public int Count; - public Dictionary AssetMap; - public Dictionary Names = new Dictionary(); + public KeyValuePair[] AssetMap; public IndexObject(ObjectReader reader) : base(reader) { Count = reader.ReadInt32(); - AssetMap = new Dictionary(Count); + AssetMap = new KeyValuePair[Count]; for (int i = 0; i < Count; i++) { - var key = reader.ReadAlignedString(); - var value = new Index(reader); - - AssetMap.Add(key, value); - - if (value.Object.m_FileID == 0) - Names.Add(value.Object.m_PathID, key); + AssetMap[i] = new KeyValuePair(reader.ReadAlignedString(), new Index(reader)); } } } diff --git a/AssetStudio/Classes/Material.cs b/AssetStudio/Classes/Material.cs index 7a69dcb..64b95e3 100644 --- a/AssetStudio/Classes/Material.cs +++ b/AssetStudio/Classes/Material.cs @@ -1,7 +1,4 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using SevenZip; -using System.Collections.Generic; +using System.Collections.Generic; namespace AssetStudio { @@ -21,94 +18,52 @@ namespace AssetStudio public class UnityPropertySheet { - private const string HDRPostfixName = "_HDR"; - private const string STPostfixName = "_ST"; - private const string TexelSizePostfixName = "_TexelSize"; - - public Dictionary m_TexEnvs; - public Dictionary m_Ints; - public Dictionary m_Floats; - public Dictionary m_Colors; + public KeyValuePair[] m_TexEnvs; + public KeyValuePair[] m_Ints; + public KeyValuePair[] m_Floats; + public KeyValuePair[] m_Colors; public UnityPropertySheet(ObjectReader reader) { var version = reader.version; int m_TexEnvsSize = reader.ReadInt32(); - m_TexEnvs = new Dictionary(m_TexEnvsSize); + m_TexEnvs = new KeyValuePair[m_TexEnvsSize]; for (int i = 0; i < m_TexEnvsSize; i++) { - m_TexEnvs.Add(reader.ReadAlignedString(), new UnityTexEnv(reader)); + m_TexEnvs[i] = new KeyValuePair(reader.ReadAlignedString(), new UnityTexEnv(reader)); } if (version[0] >= 2021) //2021.1 and up { int m_IntsSize = reader.ReadInt32(); - m_Ints = new Dictionary(m_IntsSize); + m_Ints = new KeyValuePair[m_IntsSize]; for (int i = 0; i < m_IntsSize; i++) { - m_Ints.Add(reader.ReadAlignedString(), reader.ReadInt32()); + m_Ints[i] = new KeyValuePair(reader.ReadAlignedString(), reader.ReadInt32()); } } int m_FloatsSize = reader.ReadInt32(); - m_Floats = new Dictionary(m_FloatsSize); + m_Floats = new KeyValuePair[m_FloatsSize]; for (int i = 0; i < m_FloatsSize; i++) { - m_Floats.Add(reader.ReadAlignedString(), reader.ReadSingle()); + m_Floats[i] = new KeyValuePair(reader.ReadAlignedString(), reader.ReadSingle()); } int m_ColorsSize = reader.ReadInt32(); - m_Colors = new Dictionary(m_ColorsSize); + m_Colors = new KeyValuePair[m_ColorsSize]; for (int i = 0; i < m_ColorsSize; i++) { - m_Colors.Add(reader.ReadAlignedString(), reader.ReadColor4()); + m_Colors[i] = new KeyValuePair(reader.ReadAlignedString(), reader.ReadColor4()); } } - - public string FindPropertyNameByCRC28(uint crc) - { - foreach (var property in m_TexEnvs.Keys) - { - string hdrName = property + HDRPostfixName; - if (CRC.Verify28DigestUTF8(hdrName, crc)) - { - return hdrName; - } - string stName = property + STPostfixName; - if (CRC.Verify28DigestUTF8(stName, crc)) - { - return stName; - } - string texelName = property + TexelSizePostfixName; - if (CRC.Verify28DigestUTF8(texelName, crc)) - { - return texelName; - } - } - foreach (var property in m_Floats.Keys) - { - if (CRC.Verify28DigestUTF8(property, crc)) - { - return property; - } - } - foreach (var property in m_Colors.Keys) - { - if (CRC.Verify28DigestUTF8(property, crc)) - { - return property; - } - } - return null; - } } public sealed class Material : NamedObject { public PPtr m_Shader; public UnityPropertySheet m_SavedProperties; - public Dictionary m_StringTagMap; public Material(ObjectReader reader) : base(reader) { @@ -119,16 +74,25 @@ namespace AssetStudio var m_ShaderKeywords = reader.ReadStringArray(); } - if (version[0] >= 5) //5.0 and up + if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up + { + var m_ValidKeywords = reader.ReadStringArray(); + var m_InvalidKeywords = reader.ReadStringArray(); + } + else if (version[0] >= 5) //5.0 ~ 2021.2 { var m_ShaderKeywords = reader.ReadAlignedString(); + } + + if (version[0] >= 5) //5.0 and up + { var m_LightmapFlags = reader.ReadUInt32(); } if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up { var m_EnableInstancingVariants = reader.ReadBoolean(); - var m_DoubleSidedGI = reader.ReadBoolean(); //2017 and up + //var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up reader.AlignStream(); } @@ -140,15 +104,18 @@ namespace AssetStudio if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up { var stringTagMapSize = reader.ReadInt32(); - m_StringTagMap = new Dictionary(stringTagMapSize); for (int i = 0; i < stringTagMapSize; i++) { var first = reader.ReadAlignedString(); var second = reader.ReadAlignedString(); - m_StringTagMap.Add(first, second); } } + if (reader.Game.Type.IsNaraka()) + { + var value = reader.ReadInt32(); + } + if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up { var disabledShaderPasses = reader.ReadStringArray(); @@ -158,10 +125,5 @@ namespace AssetStudio //vector m_BuildTextureStacks 2020 and up } - - public string FindPropertyNameByCRC28(uint crc) - { - return m_SavedProperties.FindPropertyNameByCRC28(crc); - } } } diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs index 5666b74..07f3959 100644 --- a/AssetStudio/Classes/Mesh.cs +++ b/AssetStudio/Classes/Mesh.cs @@ -1,12 +1,9 @@ -using SevenZip; -using System; +using System; +using System.Buffers.Binary; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection.Metadata.Ecma335; -using System.Text; -using System.Xml.Linq; namespace AssetStudio { @@ -15,7 +12,7 @@ namespace AssetStudio public Vector3 m_Min; public Vector3 m_Max; - public MinMaxAABB(BinaryReader reader) + public MinMaxAABB(EndianBinaryReader reader) { m_Min = reader.ReadVector3(); m_Max = reader.ReadVector3(); @@ -300,7 +297,6 @@ namespace AssetStudio public class MeshBlendShape { - public string name; public uint firstVertex; public uint vertexCount; public bool hasNormals; @@ -312,7 +308,7 @@ namespace AssetStudio if (version[0] == 4 && version[1] < 3) //4.3 down { - name = reader.ReadAlignedString(); + var name = reader.ReadAlignedString(); } firstVertex = reader.ReadUInt32(); vertexCount = reader.ReadUInt32(); @@ -328,11 +324,6 @@ namespace AssetStudio reader.AlignStream(); } } - - public bool IsCRCMatch(uint digest) - { - return CRC.VerifyDigestUTF8(name, digest); - } } public class MeshBlendShapeChannel @@ -404,20 +395,9 @@ namespace AssetStudio } } } - public string FindShapeNameByCRC(uint crc) - { - foreach (var blendChannel in channels) - { - if (blendChannel.nameHash == crc) - { - return blendChannel.name; - } - } - return null; - } } - public enum GfxPrimitiveType : int + public enum GfxPrimitiveType { Triangles = 0, TriangleStrip = 1, @@ -560,7 +540,7 @@ namespace AssetStudio var m_StreamCompression = reader.ReadByte(); } var m_IsReadable = reader.ReadBoolean(); - if (reader.Game.Name == "BH3") + if (reader.Game.Type.IsBH3()) { var m_IsHighPrecisionPosition = reader.ReadBoolean(); var m_IsHighPrecisionTangent = reader.ReadBoolean(); @@ -568,9 +548,9 @@ namespace AssetStudio } var m_KeepVertices = reader.ReadBoolean(); var m_KeepIndices = reader.ReadBoolean(); - reader.AlignStream(); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + reader.AlignStream(); + if (reader.Game.Type.IsGISubGroup()) { var m_PackSkinDataToUV2UV3 = reader.ReadBoolean(); reader.AlignStream(); @@ -665,7 +645,7 @@ namespace AssetStudio m_CompressedMesh = new CompressedMesh(reader); } - var m_LocalAABB = new AABB(reader); + reader.Position += 24; //AABB m_LocalAABB if (version[0] < 3 || (version[0] == 3 && version[1] <= 4)) //3.4.2 and earlier { @@ -683,19 +663,24 @@ namespace AssetStudio int m_MeshUsageFlags = reader.ReadInt32(); + if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up + { + int m_CookingOptions = reader.ReadInt32(); + } + if (version[0] >= 5) //5.0 and up { var m_BakedConvexCollisionMesh = reader.ReadUInt8Array(); reader.AlignStream(); var m_BakedTriangleCollisionMesh = reader.ReadUInt8Array(); reader.AlignStream(); - if (reader.Game.Name == "BH3") + if (reader.Game.Type.IsBH3()) { var m_MeshOptimized = reader.ReadBoolean(); } } - if (reader.Game.Name == "ZZZ_CB1") + if (reader.Game.Type.IsZZZCB1()) { var m_CloseMeshDynamicCompression = reader.ReadBoolean(); reader.AlignStream(); @@ -705,21 +690,20 @@ namespace AssetStudio var m_CompressLevelTexCoordinates = reader.ReadInt32(); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3" - || version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up + if (reader.Game.Type.IsGIGroup() || version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up { var m_MeshMetrics = new float[2]; m_MeshMetrics[0] = reader.ReadSingle(); m_MeshMetrics[1] = reader.ReadSingle(); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + if (reader.Game.Type.IsGIGroup()) { var m_MetricsDirty = reader.ReadBoolean(); reader.AlignStream(); var m_CloseMeshDynamicCompression = reader.ReadBoolean(); reader.AlignStream(); - if (reader.Game.Name != "GI_CB1") + if (!reader.Game.Type.IsGICB1() && !reader.Game.Type.IsGIPack()) { var m_IsStreamingMesh = reader.ReadBoolean(); reader.AlignStream(); @@ -830,13 +814,9 @@ namespace AssetStudio m_UV1 = componentsFloatArray; break; case 6: //kShaderChannelTexCoord2 - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") - continue; m_UV2 = componentsFloatArray; break; case 7: //kShaderChannelTexCoord3 - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") - continue; m_UV3 = componentsFloatArray; break; case 8: //kShaderChannelTexCoord4 @@ -900,8 +880,6 @@ namespace AssetStudio m_UV1 = componentsFloatArray; break; case 5: - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") - continue; if (version[0] >= 5) //kShaderChannelTexCoord2 { m_UV2 = componentsFloatArray; @@ -912,8 +890,6 @@ namespace AssetStudio } break; case 6: //kShaderChannelTexCoord3 - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") - continue; m_UV3 = componentsFloatArray; break; case 7: //kShaderChannelTangent @@ -1255,25 +1231,6 @@ namespace AssetStudio throw new ArgumentOutOfRangeException(); } } - - public string FindBlendShapeNameByCRC(uint crc) - { - if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) - { - return m_Shapes.FindShapeNameByCRC(crc); - } - else - { - foreach (var blendShape in m_Shapes.shapes) - { - if (blendShape.IsCRCMatch(crc)) - { - return blendShape.name; - } - } - return null; - } - } } public static class MeshHelper @@ -1419,7 +1376,7 @@ namespace AssetStudio switch (format) { case VertexFormat.Float: - result[i] = BitConverter.ToSingle(inputBytes, i * 4); + result[i] = BinaryPrimitives.ReadSingleLittleEndian(inputBytes.AsSpan(i * 4)); break; case VertexFormat.Float16: result[i] = Half.ToHalf(inputBytes, i * 2); @@ -1431,10 +1388,10 @@ namespace AssetStudio result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f); break; case VertexFormat.UNorm16: - result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f; + result[i] = BinaryPrimitives.ReadUInt16LittleEndian(inputBytes.AsSpan(i * 2)) / 65535f; break; case VertexFormat.SNorm16: - result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f); + result[i] = Math.Max(BinaryPrimitives.ReadInt16LittleEndian(inputBytes.AsSpan(i * 2)) / 32767f, -1f); break; } } @@ -1456,11 +1413,11 @@ namespace AssetStudio break; case VertexFormat.UInt16: case VertexFormat.SInt16: - result[i] = BitConverter.ToInt16(inputBytes, i * 2); + result[i] = BinaryPrimitives.ReadInt16LittleEndian(inputBytes.AsSpan(i * 2)); break; case VertexFormat.UInt32: case VertexFormat.SInt32: - result[i] = BitConverter.ToInt32(inputBytes, i * 4); + result[i] = BinaryPrimitives.ReadInt32LittleEndian(inputBytes.AsSpan(i * 4)); break; } } diff --git a/AssetStudio/Classes/MeshRenderer.cs b/AssetStudio/Classes/MeshRenderer.cs index 0dbcf92..7613948 100644 --- a/AssetStudio/Classes/MeshRenderer.cs +++ b/AssetStudio/Classes/MeshRenderer.cs @@ -7,9 +7,10 @@ namespace AssetStudio { public sealed class MeshRenderer : Renderer { + public PPtr m_AdditionalVertexStreams; public MeshRenderer(ObjectReader reader) : base(reader) { - var m_AdditionalVertexStreams = new PPtr(reader); + m_AdditionalVertexStreams = new PPtr(reader); } } } diff --git a/AssetStudio/Classes/MiHoYoBinData.cs b/AssetStudio/Classes/MiHoYoBinData.cs index c76e1f4..e43aeac 100644 --- a/AssetStudio/Classes/MiHoYoBinData.cs +++ b/AssetStudio/Classes/MiHoYoBinData.cs @@ -1,8 +1,8 @@ using System; using System.Text; -using System.Text.RegularExpressions; -using Newtonsoft.Json.Linq; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Text.RegularExpressions; namespace AssetStudio { @@ -12,17 +12,57 @@ namespace AssetStudio Bytes, JSON } - public sealed class MiHoYoBinData : Object + public sealed partial class MiHoYoBinData : Object { - public static bool doXOR; + public static bool Exportable; + public static bool Encrypted; public static byte Key; + public byte[] RawData; - public byte[] Data + public MiHoYoBinData(ObjectReader reader) : base(reader) + { + var length = reader.ReadInt32(); + RawData = reader.ReadBytes(length); + } + + public string AsString => Type switch + { + MiHoYoBinDataType.JSON => JToken.Parse(DataStr).ToString(Formatting.Indented), + MiHoYoBinDataType.Bytes => Chars().Replace(DataStr, string.Empty), + _ => "", + }; + public new object Dump() => Type switch + { + MiHoYoBinDataType.JSON => AsString, + MiHoYoBinDataType.Bytes => Data, + _ => null, + }; + private string DataStr => Encoding.UTF8.GetString(Data); + + public MiHoYoBinDataType Type { get { - if (doXOR) + try + { + var asToken = JToken.Parse(DataStr); + if (asToken.Type == JTokenType.Object || asToken.Type == JTokenType.Array) + return MiHoYoBinDataType.JSON; + } + catch (Exception) + { + return MiHoYoBinDataType.Bytes; + } + return MiHoYoBinDataType.None; + } + } + + private byte[] Data + { + get + { + if (Encrypted) { byte[] bytes = new byte[RawData.Length]; for (int i = 0; i < RawData.Length; i++) @@ -35,59 +75,7 @@ namespace AssetStudio } } - public string Str - { - get - { - var str = Encoding.UTF8.GetString(Data); - switch (Type) - { - case MiHoYoBinDataType.JSON: - return JToken.Parse(str).ToString(Formatting.Indented); - case MiHoYoBinDataType.Bytes: - return Regex.Replace(str, @"[^\u0020-\u007E]", string.Empty); - default: - return ""; - } - } - } - - public MiHoYoBinDataType Type - { - get - { - try - { - var str = Encoding.UTF8.GetString(Data); - var asToken = JToken.Parse(str); - if (asToken.Type == JTokenType.Object || asToken.Type == JTokenType.Array) - return MiHoYoBinDataType.JSON; - } - catch (Exception) - { - return MiHoYoBinDataType.Bytes; - } - return MiHoYoBinDataType.None; - } - } - - public MiHoYoBinData(ObjectReader reader) : base(reader) - { - var length = reader.ReadInt32(); - RawData = reader.ReadBytes(length); - } - - public new dynamic Dump() - { - switch (Type) - { - case MiHoYoBinDataType.JSON: - return Str; - case MiHoYoBinDataType.Bytes: - return Data; - default: - return null; - } - } + [GeneratedRegex("[^\\u0020-\\u007E]")] + private static partial Regex Chars(); } } diff --git a/AssetStudio/Classes/PPtr.cs b/AssetStudio/Classes/PPtr.cs index 743b7de..b31de67 100644 --- a/AssetStudio/Classes/PPtr.cs +++ b/AssetStudio/Classes/PPtr.cs @@ -1,9 +1,11 @@ using System; +using System.IO; +using System.Collections.Generic; +using static AssetStudio.AssetsHelper; namespace AssetStudio { - public sealed class PPtr : IYAMLExportable - where T : Object + public sealed class PPtr where T : Object { public int m_FileID; public long m_PathID; @@ -18,21 +20,6 @@ namespace AssetStudio assetsFile = reader.assetsFile; } - public PPtr(int fileID, long pathID, SerializedFile assetsFile) - { - m_FileID = fileID; - m_PathID = pathID; - this.assetsFile = assetsFile; - } - - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Style = MappingStyle.Flow; - node.Add("fileID", m_FileID); - return node; - } - private bool TryGetAssetsFile(out SerializedFile result) { result = null; @@ -142,11 +129,6 @@ namespace AssetStudio m_PathID = m_Object.m_PathID; } - public PPtr CastTo() where T2 : Object - { - return new PPtr(m_FileID, m_PathID, assetsFile); - } - public bool IsNull => m_PathID == 0 || m_FileID < 0; } } diff --git a/AssetStudio/Classes/Renderer.cs b/AssetStudio/Classes/Renderer.cs index f157fdb..e4181b5 100644 --- a/AssetStudio/Classes/Renderer.cs +++ b/AssetStudio/Classes/Renderer.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -20,11 +19,13 @@ namespace AssetStudio public abstract class Renderer : Component { - public static bool Parsable; + public static bool Skipped; + public PPtr[] m_Materials; public StaticBatchInfo m_StaticBatchInfo; public uint[] m_SubsetIndices; private bool isNewHeader = false; + protected Renderer(ObjectReader reader) : base(reader) { if (version[0] < 5) //5.0 down @@ -38,7 +39,7 @@ namespace AssetStudio { if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up { - if (reader.Game.Name == "GI") + if (reader.Game.Type.IsGI()) { CheckHeader(reader); } @@ -48,39 +49,44 @@ namespace AssetStudio if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up { var m_DynamicOccludee = reader.ReadByte(); - if (reader.Game.Name == "BH3") + } + if (reader.Game.Type.IsBH3()) + { + var m_AllowHalfResolution = reader.ReadByte(); + } + if (reader.Game.Type.IsGIGroup()) + { + var m_ReceiveDecals = reader.ReadByte(); + var m_EnableShadowCulling = reader.ReadByte(); + var m_EnableGpuQuery = reader.ReadByte(); + var m_AllowHalfResolution = reader.ReadByte(); + if (!reader.Game.Type.IsGICB1()) { - var m_AllowHalfResolution = reader.ReadByte(); - } - else if (reader.Game.Name == "GI_CB3") - { - var m_ReceiveDecals = reader.ReadByte(); - var m_EnableShadowCulling = reader.ReadByte(); - var m_EnableGpuQuery = reader.ReadByte(); - var m_AllowHalfResolution = reader.ReadByte(); - var m_IsRainOccluder = reader.ReadByte(); - var m_IsDynamicAOOccluder = reader.ReadByte(); - var m_IsDynamic = reader.ReadByte(); - } - else if (reader.Game.Name == "GI") - { - var m_ReceiveDecals = reader.ReadByte(); - var m_EnableShadowCulling = reader.ReadByte(); - var m_EnableGpuQuery = reader.ReadByte(); - var m_AllowHalfResolution = reader.ReadByte(); - var m_IsRainOccluder = reader.ReadByte(); - var m_IsDynamicAOOccluder = reader.ReadByte(); - var m_IsCloudObject = reader.ReadByte(); - var m_IsInteriorVolume = reader.ReadByte(); - var m_IsDynamic = reader.ReadByte(); - var m_UseTessellation = reader.ReadByte(); - var m_IsTerrainTessInfo = reader.ReadByte(); - if (isNewHeader) + if (reader.Game.Type.IsGI()) { - var m_UseVertexLightInForward = reader.ReadByte(); - var m_CombineSubMeshInGeoPass = reader.ReadByte(); - var m_AllowPerMaterialProp = reader.ReadByte(); - var m_IsHQDynamicAOOccluder = reader.ReadByte(); + var m_AllowPerMaterialProp = isNewHeader ? reader.ReadByte() : 0; + } + var m_IsRainOccluder = reader.ReadByte(); + if (!reader.Game.Type.IsGICB2()) + { + var m_IsDynamicAOOccluder = reader.ReadByte(); + if (reader.Game.Type.IsGI()) + { + var m_IsHQDynamicAOOccluder = reader.ReadByte(); + var m_IsCloudObject = reader.ReadByte(); + var m_IsInteriorVolume = reader.ReadByte(); + } + } + if (!reader.Game.Type.IsGIPack()) + { + var m_IsDynamic = reader.ReadByte(); + } + if (reader.Game.Type.IsGI()) + { + var m_UseTessellation = reader.ReadByte(); + var m_IsTerrainTessInfo = isNewHeader ? reader.ReadByte() : 0; + var m_UseVertexLightInForward = isNewHeader ? reader.ReadByte() : 0; + var m_CombineSubMeshInGeoPass = isNewHeader ? reader.ReadByte() : 0; } } } @@ -88,22 +94,6 @@ namespace AssetStudio { var m_StaticShadowCaster = reader.ReadByte(); } - if (reader.Game.Name == "GI_CB2") - { - var m_ReceiveDecals = reader.ReadByte(); - var m_EnableShadowCulling = reader.ReadByte(); - var m_EnableGpuQuery = reader.ReadByte(); - var m_AllowHalfResolution = reader.ReadByte(); - var m_IsRainOccluder = reader.ReadByte(); - var m_IsDynamic = reader.ReadByte(); - } - if (reader.Game.Name == "GI_CB1") - { - var m_ReceiveDecals = reader.ReadByte(); - var m_EnableShadowCulling = reader.ReadByte(); - var m_EnableGpuQuery = reader.ReadByte(); - var m_AllowHalfResolution = reader.ReadByte(); - } var m_MotionVectors = reader.ReadByte(); var m_LightProbeUsage = reader.ReadByte(); var m_ReflectionProbeUsage = reader.ReadByte(); @@ -115,7 +105,7 @@ namespace AssetStudio { var m_RayTraceProcedural = reader.ReadByte(); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB3") + if (reader.Game.Type.IsGI() || reader.Game.Type.IsGICB3() || reader.Game.Type.IsGICB3Pre()) { var m_MeshShowQuality = reader.ReadByte(); } @@ -140,12 +130,11 @@ namespace AssetStudio var m_RendererPriority = reader.ReadInt32(); } - var m_LightmapIndex = reader.ReadInt16(); - var m_LightmapIndexDynamic = reader.ReadInt16(); - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + var m_LightmapIndex = reader.ReadUInt16(); + var m_LightmapIndexDynamic = reader.ReadUInt16(); + if (reader.Game.Type.IsGIGroup() && (m_LightmapIndex != 0xFFFF || m_LightmapIndexDynamic != 0xFFFF)) { - if (m_LightmapIndex != -1 || m_LightmapIndexDynamic != -1) - throw new Exception("Not Supported !! skipping...."); + throw new Exception("Not Supported !! skipping...."); } } @@ -159,7 +148,7 @@ namespace AssetStudio var m_LightmapTilingOffsetDynamic = reader.ReadVector4(); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + if (reader.Game.Type.IsGIGroup()) { var m_ViewDistanceRatio = reader.ReadSingle(); var m_ShaderLODDistanceRatio = reader.ReadSingle(); @@ -188,7 +177,8 @@ namespace AssetStudio var m_StaticBatchRoot = new PPtr(reader); } - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + + if (reader.Game.Type.IsGIGroup()) { var m_MatLayers = reader.ReadInt32(); } @@ -219,21 +209,20 @@ namespace AssetStudio } else { - var m_SortingLayerID = reader.ReadInt32(); - var m_SortingLayer = reader.ReadInt16(); + var m_SortingLayerID = reader.ReadUInt32(); } //SInt16 m_SortingLayer 5.6 and up var m_SortingOrder = reader.ReadInt16(); reader.AlignStream(); - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB1" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3" || reader.Game.Name == "BH3") + if (reader.Game.Type.IsGIGroup() || reader.Game.Type.IsBH3()) { var m_UseHighestMip = reader.ReadBoolean(); reader.AlignStream(); } - if (reader.Game.Name == "SR_CB3") + if (reader.Game.Type.IsSRCB3()) { - var _RenderFlag = reader.ReadUInt32(); + var RenderFlag = reader.ReadUInt32(); reader.AlignStream(); } } @@ -241,31 +230,14 @@ namespace AssetStudio private void CheckHeader(ObjectReader reader) { - short index = 0; + short value = 0; var pos = reader.Position; - while (index != -1 && reader.Position <= pos + 0x1A) - index = reader.ReadInt16(); + while (value != -1 && reader.Position <= pos + 0x1A) + { + value = reader.ReadInt16(); + } isNewHeader = (reader.Position - pos) == 0x1A; reader.Position = pos; } - - public string FindMaterialPropertyNameByCRC28(uint crc) - { - foreach (PPtr materialPtr in m_Materials) - { - if (!materialPtr.TryGet(out var material)) - { - continue; - } - string property = material.FindPropertyNameByCRC28(crc); - if (property == null) - { - continue; - } - - return property; - } - return null; - } } } diff --git a/AssetStudio/Classes/RuntimeAnimatorController.cs b/AssetStudio/Classes/RuntimeAnimatorController.cs index 3b41073..5b6be8f 100644 --- a/AssetStudio/Classes/RuntimeAnimatorController.cs +++ b/AssetStudio/Classes/RuntimeAnimatorController.cs @@ -11,7 +11,5 @@ namespace AssetStudio { } - - public abstract bool IsContainsAnimationClip(AnimationClip clip); } } diff --git a/AssetStudio/Classes/Shader.cs b/AssetStudio/Classes/Shader.cs index a4ea97b..7bf15c1 100644 --- a/AssetStudio/Classes/Shader.cs +++ b/AssetStudio/Classes/Shader.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.IO; using System.Linq; @@ -9,7 +10,7 @@ namespace AssetStudio { public byte[] bytes; - public Hash128(BinaryReader reader) + public Hash128(EndianBinaryReader reader) { bytes = reader.ReadBytes(16); } @@ -20,7 +21,7 @@ namespace AssetStudio public MatrixParameter[] m_MatrixParams; public VectorParameter[] m_VectorParams; - public StructParameter(BinaryReader reader) + public StructParameter(EndianBinaryReader reader) { var m_NameIndex = reader.ReadInt32(); var m_Index = reader.ReadInt32(); @@ -48,7 +49,7 @@ namespace AssetStudio public uint sampler; public int bindPoint; - public SamplerParameter(BinaryReader reader) + public SamplerParameter(EndianBinaryReader reader) { sampler = reader.ReadUInt32(); bindPoint = reader.ReadInt32(); @@ -71,7 +72,7 @@ namespace AssetStudio public string m_DefaultName; public TextureDimension m_TexDim; - public SerializedTextureProperty(BinaryReader reader) + public SerializedTextureProperty(EndianBinaryReader reader) { m_DefaultName = reader.ReadAlignedString(); m_TexDim = (TextureDimension)reader.ReadInt32(); @@ -98,7 +99,7 @@ namespace AssetStudio public float[] m_DefValue; public SerializedTextureProperty m_DefTexture; - public SerializedProperty(BinaryReader reader) + public SerializedProperty(EndianBinaryReader reader) { m_Name = reader.ReadAlignedString(); m_Description = reader.ReadAlignedString(); @@ -114,7 +115,7 @@ namespace AssetStudio { public SerializedProperty[] m_Props; - public SerializedProperties(BinaryReader reader) + public SerializedProperties(EndianBinaryReader reader) { int numProps = reader.ReadInt32(); m_Props = new SerializedProperty[numProps]; @@ -130,7 +131,7 @@ namespace AssetStudio public float val; public string name; - public SerializedShaderFloatValue(BinaryReader reader) + public SerializedShaderFloatValue(EndianBinaryReader reader) { val = reader.ReadSingle(); name = reader.ReadAlignedString(); @@ -147,7 +148,7 @@ namespace AssetStudio public SerializedShaderFloatValue blendOpAlpha; public SerializedShaderFloatValue colMask; - public SerializedShaderRTBlendState(BinaryReader reader) + public SerializedShaderRTBlendState(EndianBinaryReader reader) { srcBlend = new SerializedShaderFloatValue(reader); destBlend = new SerializedShaderFloatValue(reader); @@ -166,7 +167,7 @@ namespace AssetStudio public SerializedShaderFloatValue zFail; public SerializedShaderFloatValue comp; - public SerializedStencilOp(BinaryReader reader) + public SerializedStencilOp(EndianBinaryReader reader) { pass = new SerializedShaderFloatValue(reader); fail = new SerializedShaderFloatValue(reader); @@ -183,7 +184,7 @@ namespace AssetStudio public SerializedShaderFloatValue w; public string name; - public SerializedShaderVectorValue(BinaryReader reader) + public SerializedShaderVectorValue(EndianBinaryReader reader) { x = new SerializedShaderFloatValue(reader); y = new SerializedShaderFloatValue(reader); @@ -281,7 +282,7 @@ namespace AssetStudio public sbyte source; public sbyte target; - public ShaderBindChannel(BinaryReader reader) + public ShaderBindChannel(EndianBinaryReader reader) { source = reader.ReadSByte(); target = reader.ReadSByte(); @@ -293,7 +294,7 @@ namespace AssetStudio public ShaderBindChannel[] m_Channels; public uint m_SourceMap; - public ParserBindChannels(BinaryReader reader) + public ParserBindChannels(EndianBinaryReader reader) { int numChannels = reader.ReadInt32(); m_Channels = new ShaderBindChannel[numChannels]; @@ -315,7 +316,7 @@ namespace AssetStudio public sbyte m_Type; public sbyte m_Dim; - public VectorParameter(BinaryReader reader) + public VectorParameter(EndianBinaryReader reader) { m_NameIndex = reader.ReadInt32(); m_Index = reader.ReadInt32(); @@ -334,7 +335,7 @@ namespace AssetStudio public sbyte m_Type; public sbyte m_RowCount; - public MatrixParameter(BinaryReader reader) + public MatrixParameter(EndianBinaryReader reader) { m_NameIndex = reader.ReadInt32(); m_Index = reader.ReadInt32(); @@ -428,6 +429,7 @@ namespace AssetStudio if ((version[0] == 2020 && version[1] > 3) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up + (version[0] > 2021) || (version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up { @@ -443,7 +445,7 @@ namespace AssetStudio public int m_Index; public int m_OriginalIndex; - public UAVParameter(BinaryReader reader) + public UAVParameter(EndianBinaryReader reader) { m_NameIndex = reader.ReadInt32(); m_Index = reader.ReadInt32(); @@ -605,6 +607,7 @@ namespace AssetStudio if ((version[0] == 2020 && version[1] > 3) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up + (version[0] > 2021) || (version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up { @@ -690,6 +693,7 @@ namespace AssetStudio { public SerializedSubProgram[] m_SubPrograms; public SerializedProgramParameters m_CommonParameters; + public ushort[] m_SerializedKeywordStateMask; public SerializedProgram(ObjectReader reader) { @@ -704,11 +708,18 @@ namespace AssetStudio if ((version[0] == 2020 && version[1] > 3) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up + (version[0] > 2021) || (version[0] == 2021 && version[1] > 1) || - (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.4f1 and up + (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up { m_CommonParameters = new SerializedProgramParameters(reader); } + + if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up + { + m_SerializedKeywordStateMask = reader.ReadUInt16Array(); + reader.AlignStream(); + } } } @@ -795,7 +806,7 @@ namespace AssetStudio m_Name = reader.ReadAlignedString(); m_TextureName = reader.ReadAlignedString(); m_Tags = new SerializedTagMap(reader); - if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up + if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x { m_SerializedKeywordStateMask = reader.ReadUInt16Array(); reader.AlignStream(); @@ -807,7 +818,7 @@ namespace AssetStudio { public KeyValuePair[] tags; - public SerializedTagMap(BinaryReader reader) + public SerializedTagMap(EndianBinaryReader reader) { int numTags = reader.ReadInt32(); tags = new KeyValuePair[numTags]; @@ -843,7 +854,7 @@ namespace AssetStudio public string from; public string to; - public SerializedShaderDependency(BinaryReader reader) + public SerializedShaderDependency(EndianBinaryReader reader) { from = reader.ReadAlignedString(); to = reader.ReadAlignedString(); @@ -855,7 +866,7 @@ namespace AssetStudio public string customEditorName; public string renderPipelineType; - public SerializedCustomEditorForRenderPipeline(BinaryReader reader) + public SerializedCustomEditorForRenderPipeline(EndianBinaryReader reader) { customEditorName = reader.ReadAlignedString(); renderPipelineType = reader.ReadAlignedString(); @@ -953,7 +964,6 @@ namespace AssetStudio public class Shader : NamedObject { - public static bool Parsable; public byte[] m_Script; //5.3 - 5.4 public uint decompressedSize; @@ -985,22 +995,22 @@ namespace AssetStudio decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray(); } compressedBlob = reader.ReadUInt8Array(); - if (reader.Game.Name == "GI" || reader.Game.Name == "GI_CB2" || reader.Game.Name == "GI_CB3") + reader.AlignStream(); + if (reader.Game.Type.IsGISubGroup()) { - if (BitConverter.ToInt32(compressedBlob, 0) == -1) - compressedBlob = reader.ReadUInt8Array(); + if (BinaryPrimitives.ReadInt32LittleEndian(compressedBlob) == -1) + { + compressedBlob = reader.ReadUInt8Array(); //blobDataBlocks + reader.AlignStream(); + } } - else - { - reader.AlignStream(); - } - + var m_DependenciesCount = reader.ReadInt32(); for (int i = 0; i < m_DependenciesCount; i++) { new PPtr(reader); } - + if (version[0] >= 2018) { var m_NonModifiableTexturesCount = reader.ReadInt32(); @@ -1010,7 +1020,7 @@ namespace AssetStudio new PPtr(reader); } } - + var m_ShaderIsBaked = reader.ReadBoolean(); reader.AlignStream(); } diff --git a/AssetStudio/Classes/SkinnedMeshRenderer.cs b/AssetStudio/Classes/SkinnedMeshRenderer.cs index 8c26fbd..d189641 100644 --- a/AssetStudio/Classes/SkinnedMeshRenderer.cs +++ b/AssetStudio/Classes/SkinnedMeshRenderer.cs @@ -9,11 +9,12 @@ namespace AssetStudio { public PPtr m_Mesh; public PPtr[] m_Bones; - public PPtr m_RootBone; public float[] m_BlendShapeWeights; + public PPtr m_RootBone; public AABB m_AABB; public bool m_DirtyAABB; + public SkinnedMeshRenderer(ObjectReader reader) : base(reader) { int m_Quality = reader.ReadInt32(); @@ -33,16 +34,19 @@ namespace AssetStudio { m_Bones[b] = new PPtr(reader); } - reader.AlignStream(); + if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up { m_BlendShapeWeights = reader.ReadSingleArray(); } - reader.AlignStream(); - m_RootBone = new PPtr(reader); - m_AABB = new AABB(reader); - m_DirtyAABB = reader.ReadBoolean(); - reader.AlignStream(); + + if (reader.Game.Type.IsGIGroup()) + { + m_RootBone = new PPtr(reader); + m_AABB = new AABB(reader); + m_DirtyAABB = reader.ReadBoolean(); + reader.AlignStream(); + } } } } diff --git a/AssetStudio/Classes/Texture2D.cs b/AssetStudio/Classes/Texture2D.cs index dcbc466..73107ae 100644 --- a/AssetStudio/Classes/Texture2D.cs +++ b/AssetStudio/Classes/Texture2D.cs @@ -1,5 +1,4 @@ using System; -using System.IO; namespace AssetStudio { @@ -134,9 +133,13 @@ namespace AssetStudio ResourceReader resourceReader; if (!string.IsNullOrEmpty(m_StreamData?.path)) + { resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size); + } else + { resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size); + } image_data = resourceReader; } } @@ -204,7 +207,7 @@ namespace AssetStudio R8, ETC_RGB4Crunched, ETC2_RGBA8Crunched, - R16_2, + R16_Alt, ASTC_HDR_4x4, ASTC_HDR_5x5, ASTC_HDR_6x6, diff --git a/AssetStudio/Classes/Transform.cs b/AssetStudio/Classes/Transform.cs index 3fe12a9..4e730a0 100644 --- a/AssetStudio/Classes/Transform.cs +++ b/AssetStudio/Classes/Transform.cs @@ -27,32 +27,5 @@ namespace AssetStudio } m_Father = new PPtr(reader); } - - public Transform FindChild(string path) - { - if (path.Length == 0) - { - return this; - } - return FindChild(path, 0); - } - private Transform FindChild(string path, int startIndex) - { - int separatorIndex = path.IndexOf('/', startIndex); - string childName = separatorIndex == -1 ? - path.Substring(startIndex, path.Length - startIndex) : - path.Substring(startIndex, separatorIndex - startIndex); - foreach (PPtr childPtr in m_Children) - { - if(childPtr.TryGet(out var child)) - { - if (child.m_GameObject.TryGet(out var childGO) && childGO.m_Name == childName) - { - return separatorIndex == -1 ? child : child.FindChild(path, separatorIndex + 1); - } - } - } - return null; - } } } diff --git a/AssetStudio/Classes/VideoClip.cs b/AssetStudio/Classes/VideoClip.cs index 730edfd..a5af6f9 100644 --- a/AssetStudio/Classes/VideoClip.cs +++ b/AssetStudio/Classes/VideoClip.cs @@ -8,7 +8,7 @@ namespace AssetStudio public long m_Offset; //ulong public long m_Size; //ulong - public StreamedResource(BinaryReader reader) + public StreamedResource(EndianBinaryReader reader) { m_Source = reader.ReadAlignedString(); m_Offset = reader.ReadInt64(); diff --git a/AssetStudio/Game/Crypto/AES.cs b/AssetStudio/Crypto/AES.cs similarity index 100% rename from AssetStudio/Game/Crypto/AES.cs rename to AssetStudio/Crypto/AES.cs diff --git a/AssetStudio/Crypto/BlkUtils.cs b/AssetStudio/Crypto/BlkUtils.cs new file mode 100644 index 0000000..7bf727e --- /dev/null +++ b/AssetStudio/Crypto/BlkUtils.cs @@ -0,0 +1,59 @@ +using System; +using System.Buffers.Binary; + +namespace AssetStudio +{ + public static class BlkUtils + { + private const int KeySize = 0x1000; + private const int SeedBlockSize = 0x800; + + public static CryptoStream Decrypt(FileReader reader, Blk blk) + { + reader.Endian = EndianType.LittleEndian; + + var signature = reader.ReadStringToNull(); + var count = reader.ReadInt32(); + var key = reader.ReadBytes(count); + reader.Position += count; + var seedSize = Math.Min(reader.ReadInt16(), blk.SBox.IsNullOrEmpty() ? SeedBlockSize : SeedBlockSize * 2); + + if (!blk.SBox.IsNullOrEmpty() && blk.Type.IsGI()) + { + for (int i = 0; i < 0x10; i++) + { + key[i] = blk.SBox[(i % 4 * 0x100) | key[i]]; + } + } + + AES.Decrypt(key, blk.ExpansionKey); + + for (int i = 0; i < 0x10; i++) + { + key[i] ^= blk.InitVector[i]; + } + + ulong keySeed = ulong.MaxValue; + + var dataPos = reader.Position; + for (int i = 0; i < seedSize; i += 8) + { + keySeed ^= reader.ReadUInt64(); + } + reader.Position = dataPos; + + var keyLow = BinaryPrimitives.ReadUInt64LittleEndian(key.AsSpan(0, 8)); + var keyHigh = BinaryPrimitives.ReadUInt64LittleEndian(key.AsSpan(8, 8)); + var seed = keyLow ^ keyHigh ^ keySeed ^ blk.InitSeed; + + MT19937_64.Init(seed); + var xorpad = new byte[KeySize]; + for (int i = 0; i < KeySize; i += 8) + { + BinaryPrimitives.WriteUInt64LittleEndian(xorpad.AsSpan(i, 8), MT19937_64.Int64()); + } + + return new CryptoStream(reader.BaseStream, xorpad); + } + } +} \ No newline at end of file diff --git a/AssetStudio/Crypto/CNUnity.cs b/AssetStudio/Crypto/CNUnity.cs new file mode 100644 index 0000000..ea91e94 --- /dev/null +++ b/AssetStudio/Crypto/CNUnity.cs @@ -0,0 +1,164 @@ +using System; +using System.Text; +using System.Security.Cryptography; + +namespace AssetStudio +{ + public class CNUnity + { + private const string Signature = "#$unity3dchina!@"; + + public static ICryptoTransform Encryptor; + + public byte[] Index = new byte[0x10]; + public byte[] Sub = new byte[0x10]; + + public CNUnity(EndianBinaryReader reader) + { + reader.ReadUInt32(); + + var infoBytes = reader.ReadBytes(0x10); + var infoKey = reader.ReadBytes(0x10); + reader.Position += 1; + + var signatureBytes = reader.ReadBytes(0x10); + var signatureKey = reader.ReadBytes(0x10); + reader.Position += 1; + + DecryptKey(signatureKey, signatureBytes); + + var str = Encoding.UTF8.GetString(signatureBytes); + if (str != Signature) + throw new Exception("Invalid Signature !!"); + + DecryptKey(infoKey, infoBytes); + + infoBytes = infoBytes.ToUInt4Array(); + infoBytes.AsSpan(0, 0x10).CopyTo(Index); + var subBytes = infoBytes.AsSpan(0x10, 0x10); + for (var i = 0; i < subBytes.Length; i++) + { + var idx = (i % 4 * 4) + (i / 4); + Sub[idx] = subBytes[i]; + } + } + + public static bool SetKey(Entry entry) + { + try + { + using var aes = Aes.Create(); + aes.Mode = CipherMode.ECB; + aes.Key = Encoding.UTF8.GetBytes(entry.Key); + + Encryptor = aes.CreateEncryptor(); + } + catch(Exception e) + { + Logger.Error($"[CNUnity] Invalid key !!\n{e.Message}"); + return false; + } + return true; + } + + public void DecryptBlock(Span bytes, int size, int index) + { + var offset = 0; + while (offset < size) + { + offset += Decrypt(bytes[offset..], index++, size - offset); + } + } + + private void DecryptKey(byte[] key, byte[] data) + { + if (Encryptor != null) + { + key = Encryptor.TransformFinalBlock(key, 0, key.Length); + for (int i = 0; i < 0x10; i++) + data[i] ^= key[i]; + } + } + + private int DecryptByte(Span bytes, ref int offset, ref int index) + { + var b = Sub[((index >> 2) & 3) + 4] + Sub[index & 3] + Sub[((index >> 4) & 3) + 8] + Sub[((byte)index >> 6) + 12]; + bytes[offset] = (byte)((Index[bytes[offset] & 0xF] - b) & 0xF | 0x10 * (Index[bytes[offset] >> 4] - b)); + b = bytes[offset]; + offset++; + index++; + return b; + } + + private int Decrypt(Span bytes, int index, int remaining) + { + var offset = 0; + + var curByte = DecryptByte(bytes, ref offset, ref index); + var byteHigh = curByte >> 4; + var byteLow = curByte & 0xF; + + if (byteHigh == 0xF) + { + int b; + do + { + b = DecryptByte(bytes, ref offset, ref index); + byteHigh += b; + } while (b == 0xFF); + } + + offset += byteHigh; + + if (offset < remaining) + { + DecryptByte(bytes, ref offset, ref index); + DecryptByte(bytes, ref offset, ref index); + if (byteLow == 0xF) + { + int b; + do + { + b = DecryptByte(bytes, ref offset, ref index); + } while(b == 0xFF); + } + } + + return offset; + } + + public record Entry + { + public string Name { get; private set; } + public string Key { get; private set; } + + public Entry(string name, string key) + { + Name = name; + Key = key; + } + + public bool Validate() + { + try + { + var bytes = Encoding.UTF8.GetBytes(Key); + if (bytes.Length != 0x10) + { + Logger.Warning($"[CNUnity] {this} has invalid key, size should be 16 bytes, skipping..."); + return false; + } + } + catch(Exception e) + { + Logger.Error($"[CNUnity] Error while adding {this}: {e.Message}"); + return false; + } + + return true; + } + + public override string ToString() => $"{Name} ({Key})"; + } + } +} \ No newline at end of file diff --git a/AssetStudio/Crypto/CryptoHelper.cs b/AssetStudio/Crypto/CryptoHelper.cs new file mode 100644 index 0000000..c77c4ae --- /dev/null +++ b/AssetStudio/Crypto/CryptoHelper.cs @@ -0,0 +1,59 @@ +using System; + +namespace AssetStudio +{ + public static class Crypto + { + #region GI + public static readonly byte[] GISBox = new byte[] { 0xF7, 0xE7, 0xD8, 0xB8, 0x64, 0x31, 0xD1, 0x74, 0x88, 0xAA, 0xB4, 0x8B, 0x6A, 0xA3, 0xFC, 0x55, 0x59, 0xC5, 0x6D, 0xC9, 0x9A, 0x11, 0x2F, 0x37, 0xAD, 0x35, 0x15, 0x62, 0x61, 0x04, 0x44, 0x01, 0xDD, 0x47, 0x3D, 0xFF, 0x8F, 0x51, 0xAF, 0x0F, 0x19, 0x23, 0x92, 0x13, 0x00, 0x53, 0x4B, 0x67, 0x21, 0x1C, 0x1B, 0x94, 0xE2, 0x29, 0x9F, 0x4C, 0xFB, 0xBB, 0x75, 0xF0, 0xFE, 0x1F, 0xDB, 0xEF, 0x1D, 0xF1, 0x3A, 0x1A, 0x05, 0x06, 0xCE, 0xDE, 0x63, 0x0A, 0x6B, 0x2D, 0x28, 0x41, 0x6C, 0x0C, 0x42, 0xDC, 0x58, 0xB6, 0x39, 0x2E, 0xD2, 0xF6, 0x2B, 0xAC, 0x84, 0x96, 0x17, 0xF3, 0x3F, 0x8D, 0xAB, 0x95, 0xCD, 0x30, 0x0E, 0x66, 0x90, 0xF4, 0xED, 0xE0, 0x8E, 0xC2, 0x78, 0x2C, 0x7E, 0xF8, 0x5D, 0x02, 0x91, 0xFA, 0x3C, 0xDA, 0xB7, 0x6F, 0xF9, 0x4F, 0x14, 0x5E, 0xEA, 0x24, 0x56, 0x9E, 0xC1, 0xA5, 0x85, 0xD7, 0x08, 0x83, 0x4E, 0xF5, 0x76, 0x32, 0x86, 0x5C, 0xD3, 0x09, 0x5F, 0xFD, 0x36, 0x03, 0xEE, 0xE3, 0x34, 0x77, 0x79, 0x18, 0xBD, 0xDF, 0x97, 0x71, 0xBA, 0x65, 0x68, 0x7A, 0x54, 0x80, 0x48, 0x38, 0x5B, 0x4D, 0x5A, 0x7F, 0x0B, 0x7C, 0xA6, 0x7B, 0x25, 0xD6, 0x0D, 0x40, 0xD0, 0x07, 0x99, 0x9D, 0x93, 0x69, 0xD9, 0x8C, 0xB3, 0xB5, 0xA4, 0x1E, 0xCB, 0x33, 0x82, 0xE9, 0xC3, 0x60, 0xA7, 0xAE, 0x45, 0xBE, 0xB1, 0x46, 0xB2, 0x9C, 0x22, 0xC7, 0x81, 0x98, 0xA9, 0xD5, 0x6E, 0xE1, 0x10, 0xCA, 0xBC, 0x4A, 0x70, 0xD4, 0xC4, 0x72, 0x12, 0xCF, 0x2A, 0x87, 0x16, 0xC8, 0x73, 0xA1, 0x3E, 0x52, 0x50, 0xA8, 0x57, 0x27, 0xEC, 0xCC, 0x7D, 0xE4, 0xA0, 0x89, 0xBF, 0xE5, 0x8A, 0x20, 0xEB, 0xC0, 0xA2, 0x49, 0xB9, 0xE8, 0x26, 0xC6, 0xE6, 0xB0, 0x3B, 0x9B, 0xF2, 0x43, 0x5E, 0xB0, 0xE6, 0x0D, 0xF9, 0x87, 0xD7, 0x8A, 0xDF, 0xE7, 0x19, 0x99, 0x6F, 0xD5, 0x5B, 0x4E, 0xCB, 0xC2, 0x48, 0xD2, 0xF2, 0x44, 0x35, 0x03, 0xE9, 0x86, 0xD0, 0x95, 0x02, 0x4A, 0x04, 0x62, 0xC5, 0x9D, 0x1D, 0xE2, 0xFD, 0x53, 0x08, 0x8D, 0x5D, 0x75, 0xD9, 0x3F, 0x94, 0x59, 0x14, 0x29, 0x98, 0x76, 0x8C, 0x79, 0x2E, 0x8F, 0x39, 0x0C, 0x4C, 0xC8, 0xC0, 0x81, 0x9C, 0x10, 0xBB, 0xAF, 0xF7, 0xE5, 0xB2, 0xB3, 0xEE, 0x56, 0x57, 0xB8, 0xFA, 0x40, 0x7A, 0x72, 0x77, 0x24, 0x6C, 0xC6, 0x47, 0x3A, 0x74, 0xCF, 0x89, 0xB4, 0x9B, 0x26, 0xAA, 0x38, 0x09, 0xC3, 0x1C, 0xDE, 0x9F, 0xDD, 0x16, 0x1F, 0x55, 0xBD, 0xAD, 0xAC, 0x80, 0x4F, 0x64, 0x4B, 0x71, 0xB7, 0xF6, 0x06, 0x2B, 0xC7, 0x01, 0xEA, 0x46, 0xA6, 0xEB, 0x3D, 0xCA, 0x07, 0x34, 0x1B, 0xFF, 0x7C, 0x7D, 0x2D, 0x37, 0x67, 0x60, 0x9A, 0xC4, 0x97, 0x7F, 0xD6, 0xBE, 0xAE, 0x85, 0x25, 0x88, 0x65, 0xA2, 0x00, 0xB6, 0x8E, 0xD4, 0x6E, 0x1A, 0x63, 0x36, 0x92, 0xC1, 0xE1, 0x15, 0xA5, 0x58, 0x3B, 0x7E, 0x22, 0x2F, 0x84, 0x0F, 0x5C, 0x96, 0xB1, 0xF1, 0x6D, 0x8B, 0xF4, 0xA8, 0xB5, 0x0B, 0xFE, 0x23, 0xE3, 0xCE, 0xF8, 0xF5, 0x51, 0x45, 0x43, 0x18, 0x1E, 0xD1, 0xBA, 0xBC, 0x90, 0x21, 0x70, 0x30, 0xC9, 0x2A, 0xEC, 0x61, 0x7B, 0x66, 0x5F, 0x13, 0x33, 0x20, 0x6B, 0xCD, 0x3C, 0xA0, 0x93, 0x31, 0xB9, 0x05, 0x82, 0xFB, 0x3E, 0x17, 0x12, 0x6A, 0x0A, 0xCC, 0x4D, 0xA1, 0x73, 0x52, 0x78, 0xBF, 0x28, 0x50, 0x69, 0xDC, 0x68, 0x42, 0xE0, 0xA4, 0x2C, 0xEF, 0xF0, 0x11, 0xE8, 0x91, 0x49, 0x83, 0x5A, 0xF3, 0x32, 0xDB, 0xAB, 0xDA, 0x27, 0x0E, 0xED, 0xA3, 0xFC, 0x41, 0xA7, 0xA9, 0xD3, 0x9E, 0xE4, 0xD8, 0x54, 0x95, 0xAE, 0xF0, 0xD5, 0x73, 0x24, 0xD2, 0xA5, 0x99, 0x0B, 0x1B, 0xC4, 0x9A, 0xD8, 0x69, 0x6F, 0x25, 0xED, 0x8E, 0x91, 0x63, 0xF8, 0x35, 0x62, 0x5B, 0x94, 0x88, 0xB2, 0x5C, 0x0F, 0xDD, 0xA4, 0x7A, 0x1A, 0x12, 0xC6, 0x37, 0x44, 0xF1, 0x4E, 0xB9, 0x4D, 0x43, 0xD1, 0xAD, 0xEB, 0xB4, 0x46, 0x80, 0x30, 0x5E, 0xE4, 0x87, 0x6E, 0x0A, 0x82, 0xCF, 0x74, 0x38, 0xB5, 0xC1, 0xD6, 0x01, 0x05, 0xE8, 0x83, 0xA9, 0x6D, 0xCE, 0xA8, 0xC5, 0x51, 0xA3, 0x3F, 0xDA, 0x03, 0xD0, 0x3A, 0x39, 0x6C, 0x11, 0x97, 0x68, 0x54, 0xC0, 0x4B, 0xDF, 0x19, 0x0C, 0x21, 0x1F, 0x66, 0xBD, 0xE9, 0x61, 0x49, 0xC8, 0x42, 0xBC, 0xEC, 0x7F, 0xC3, 0x4F, 0x2E, 0xA1, 0x58, 0x3D, 0x81, 0xE3, 0x14, 0xB8, 0x02, 0x23, 0x9E, 0x77, 0x2B, 0x33, 0xA6, 0x93, 0x13, 0x34, 0x0E, 0x06, 0x45, 0xFB, 0x07, 0x75, 0x0D, 0x1E, 0x40, 0xAB, 0x7D, 0xF5, 0xBB, 0x55, 0xEF, 0x04, 0x65, 0x79, 0x2F, 0xCA, 0xF3, 0x29, 0xCB, 0xEA, 0x17, 0xF4, 0xE6, 0x71, 0x4C, 0x50, 0x26, 0xD9, 0x78, 0x5F, 0x09, 0x9C, 0x1C, 0x85, 0x31, 0x22, 0x9B, 0xC9, 0xE0, 0x8F, 0xAC, 0x57, 0x8B, 0x7C, 0x47, 0x7E, 0x16, 0xF7, 0x08, 0x5A, 0x59, 0x1D, 0xC7, 0xF9, 0x00, 0x2D, 0x60, 0x3C, 0x9F, 0x96, 0xA2, 0xBA, 0x20, 0x70, 0xF6, 0x48, 0xB0, 0x2C, 0x72, 0xE1, 0x64, 0xE7, 0xFF, 0xB7, 0x56, 0xA7, 0x53, 0x84, 0xD7, 0xE2, 0xD4, 0xA0, 0xB1, 0x8C, 0xE5, 0x2A, 0xDC, 0x15, 0x28, 0x5D, 0x3B, 0x36, 0x7B, 0x86, 0x6A, 0xDB, 0x10, 0xBE, 0x6B, 0xFE, 0x9D, 0x18, 0xDE, 0x76, 0xF2, 0xCD, 0xB6, 0x32, 0xFC, 0x41, 0xAF, 0xBF, 0x67, 0xB3, 0xAA, 0xC2, 0x8A, 0xFD, 0x89, 0xCC, 0xFA, 0x90, 0x98, 0x8D, 0x52, 0xD3, 0xEE, 0x92, 0x3E, 0x4A, 0x27, 0x2A, 0xD7, 0x9E, 0x02, 0x53, 0x63, 0xEA, 0xE9, 0x8F, 0x35, 0x22, 0x7F, 0xFE, 0xCA, 0x75, 0x46, 0x57, 0x94, 0xD9, 0x4E, 0xD2, 0xD4, 0x76, 0xA1, 0xC3, 0xD8, 0xBC, 0x9B, 0x84, 0x87, 0x91, 0x51, 0xB1, 0xAB, 0x81, 0x64, 0x47, 0xAF, 0x9D, 0x6A, 0x5B, 0x2D, 0xD6, 0x95, 0x77, 0x03, 0xC1, 0x10, 0xAD, 0x61, 0x0C, 0xBF, 0x11, 0x34, 0x7E, 0x01, 0x38, 0x20, 0x4B, 0xB6, 0x4A, 0x1A, 0x45, 0x99, 0x5F, 0x26, 0xBB, 0xC5, 0xCD, 0x23, 0xF1, 0xF7, 0xB4, 0x8E, 0xE1, 0xF8, 0x68, 0x56, 0x29, 0xD5, 0x3D, 0xEF, 0x12, 0x28, 0xC4, 0x2E, 0x79, 0xA6, 0x48, 0x85, 0x73, 0x14, 0xE4, 0xC6, 0x6B, 0x92, 0x30, 0x27, 0x93, 0x13, 0x0D, 0xE2, 0xC9, 0xF0, 0x65, 0xDF, 0xFB, 0xE3, 0x06, 0x2F, 0x8C, 0x4C, 0x18, 0x15, 0xD3, 0x49, 0x3E, 0x07, 0x59, 0xB0, 0x88, 0xA9, 0xC8, 0x3B, 0x86, 0xEE, 0x5C, 0x7A, 0x5E, 0xFF, 0x8D, 0xAC, 0x08, 0xE6, 0x60, 0x54, 0xA0, 0x7D, 0x40, 0x33, 0xA8, 0xFC, 0xE0, 0x37, 0x98, 0xBD, 0xEC, 0x09, 0xB2, 0x71, 0x58, 0x1F, 0xDE, 0x74, 0x89, 0x36, 0x52, 0x66, 0xA2, 0x3C, 0x96, 0x5D, 0x50, 0x90, 0x41, 0xF5, 0x17, 0x2B, 0x0B, 0xDC, 0xF6, 0x00, 0x83, 0xDD, 0x6D, 0xB5, 0x3A, 0x9C, 0xB8, 0x70, 0x7C, 0x43, 0x69, 0xFD, 0x32, 0x1B, 0xED, 0x0F, 0x55, 0x97, 0xC2, 0xFA, 0x39, 0x4F, 0x9A, 0x82, 0x19, 0xE7, 0x78, 0x6E, 0xCB, 0xA4, 0xBE, 0x24, 0xB3, 0xF3, 0xCC, 0xCF, 0x1C, 0xF9, 0x44, 0xA5, 0x1E, 0x80, 0x3F, 0xD0, 0x21, 0xA3, 0xE8, 0x31, 0x05, 0x16, 0x8A, 0xBA, 0x67, 0x0E, 0xE5, 0xB7, 0xD1, 0x42, 0x1D, 0xDB, 0x72, 0x6C, 0xA7, 0xCE, 0x04, 0x4D, 0xDA, 0xC7, 0x8B, 0x9F, 0x6F, 0x0A, 0x2C, 0xEB, 0xF2, 0x5A, 0x7B, 0xAA, 0x25, 0xC0, 0x62, 0xAE, 0xF4, 0xB9 }; + public static readonly byte[] GIExpansionKey = new byte[] { 0x54, 0x2F, 0xED, 0x67, 0x5D, 0xDD, 0x11, 0x2E, 0xB7, 0x40, 0x13, 0xE3, 0x29, 0xAB, 0x6D, 0x28, 0x3E, 0xD0, 0x4D, 0x51, 0xD3, 0x0B, 0x8F, 0x3C, 0x8F, 0x7D, 0x56, 0x0D, 0xB3, 0x5C, 0x5B, 0xDF, 0x8F, 0x05, 0x26, 0xE5, 0x9D, 0x36, 0xEE, 0x17, 0xF9, 0x40, 0xC3, 0x05, 0x6A, 0xF1, 0x1D, 0x2C, 0x79, 0xED, 0xC6, 0xE2, 0x0C, 0x15, 0x87, 0x93, 0xC1, 0x91, 0xE5, 0x8D, 0x44, 0x10, 0x98, 0x34, 0x08, 0x7A, 0xB6, 0x76, 0xAA, 0xB5, 0x34, 0x21, 0xEE, 0x72, 0x58, 0x27, 0x3F, 0x72, 0x5A, 0x93, 0x75, 0x78, 0x60, 0xC0, 0xA2, 0xF5, 0x52, 0x97, 0x9F, 0xF5, 0x28, 0x86, 0x23, 0x3A, 0xB4, 0xEA, 0xC3, 0x40, 0x12, 0x39, 0x92, 0xE2, 0x33, 0xD8, 0x7A, 0x39, 0x44, 0xA9, 0x5B, 0x58, 0x5F, 0x7C, 0xD9, 0xFC, 0x9F, 0xEF, 0x3F, 0x3A, 0x05, 0x5B, 0xA5, 0x4D, 0x1D, 0x63, 0x33, 0xD5, 0xEB, 0x43, 0x42, 0x79, 0x71, 0x85, 0x57, 0x92, 0xF8, 0xDE, 0xED, 0x7D, 0xE3, 0xF8, 0x33, 0x20, 0x2C, 0x92, 0x22, 0xE5, 0x6E, 0xCC, 0x1D, 0x21, 0x71, 0x04, 0xB8, 0xA7, 0x8D, 0x3B, 0xE6, 0x19, 0x53, 0x36, 0x1E, 0x14, 0x40, 0x12, 0xED, 0x7B, 0x85, 0x47, 0x8D, 0xD2, 0xCD, 0xF8, 0x4D, 0x71, 0xBC, 0x62 }; + public static readonly byte[] GIInitVector = new byte[] { 0xE3, 0xFC, 0x2D, 0x26, 0x9C, 0xC5, 0xA2, 0xEC, 0xD3, 0xF8, 0xC6, 0xD3, 0x77, 0xC2, 0x49, 0xB9 }; + public static readonly byte[] GIMhy0ShiftRow = new byte[] { 0x0B, 0x02, 0x08, 0x0C, 0x01, 0x05, 0x00, 0x0F, 0x06, 0x07, 0x09, 0x03, 0x0D, 0x04, 0x0E, 0x0A, 0x04, 0x05, 0x07, 0x0A, 0x02, 0x0F, 0x0B, 0x08, 0x0E, 0x0D, 0x09, 0x06, 0x0C, 0x03, 0x00, 0x01, 0x08, 0x00, 0x0C, 0x06, 0x04, 0x0B, 0x07, 0x09, 0x05, 0x03, 0x0F, 0x01, 0x0D, 0x0A, 0x02, 0x0E }; + public static readonly byte[] GIMhy0Key = new byte[] { 0x48, 0x14, 0x36, 0xED, 0x8E, 0x44, 0x5B, 0xB6 }; + public static readonly byte[] GIMhy0Mul = new byte[] { 0xA7, 0x99, 0x66, 0x50, 0xB9, 0x2D, 0xF0, 0x78 }; + public static readonly ulong GIInitSeed = 0x567BA22BABB08098; + #endregion + + #region CBX + public static readonly byte[] GI_CBXSBox = new byte[] { 0x42, 0x78, 0x81, 0xD1, 0xDD, 0x1A, 0xDC, 0xFD, 0x5F, 0x4E, 0x31, 0xE0, 0x02, 0x46, 0x4D, 0xBF, 0x3D, 0xF7, 0xD7, 0x71, 0xC0, 0x21, 0xB4, 0x63, 0x1E, 0xE3, 0x25, 0xAB, 0x69, 0x09, 0xF5, 0x0D, 0x82, 0x3E, 0x23, 0x22, 0x0F, 0x4A, 0x9D, 0x03, 0x01, 0xE5, 0x07, 0x11, 0xB5, 0xBE, 0xD5, 0xD0, 0x3B, 0x84, 0x9A, 0xDE, 0x6E, 0x6D, 0x8F, 0xB1, 0x33, 0x50, 0xFE, 0x62, 0x93, 0x2B, 0x05, 0xDB, 0x3F, 0x9B, 0xD3, 0x68, 0xC7, 0x91, 0x8B, 0x6C, 0xF0, 0xA9, 0x17, 0xF9, 0xB9, 0x8D, 0x56, 0x08, 0xEA, 0x79, 0xA4, 0x41, 0xCF, 0x04, 0x52, 0x2C, 0x32, 0x9F, 0xA2, 0xFA, 0x30, 0xC1, 0x55, 0x00, 0x54, 0x61, 0xBC, 0x47, 0x7F, 0xB7, 0x36, 0xAD, 0x97, 0x5E, 0xF4, 0x5B, 0xD8, 0xEB, 0x35, 0x3A, 0x2E, 0x29, 0x70, 0x6F, 0x13, 0x12, 0x9C, 0xE6, 0xDA, 0x4C, 0x38, 0x19, 0x59, 0xE9, 0x7B, 0xEF, 0xC3, 0x95, 0x60, 0xD6, 0x5A, 0x44, 0x58, 0xF1, 0xC8, 0xA1, 0xD4, 0x88, 0x65, 0xED, 0x28, 0xFB, 0x3C, 0x39, 0x87, 0xE4, 0x1D, 0x99, 0xCB, 0xFC, 0x0E, 0x57, 0x2A, 0x8C, 0x94, 0x5C, 0x45, 0x7D, 0xAF, 0x64, 0x9E, 0x74, 0x49, 0x4B, 0xC2, 0x7E, 0xAA, 0xE7, 0xB2, 0xEE, 0xBD, 0xA3, 0x72, 0x24, 0xB0, 0x8E, 0x7A, 0xB8, 0x8A, 0x37, 0x6B, 0x83, 0x85, 0x67, 0x77, 0x0A, 0xBA, 0x1C, 0x80, 0x0B, 0x96, 0x10, 0x1B, 0xEC, 0xFF, 0x53, 0xF6, 0x14, 0xA7, 0xF8, 0x27, 0x40, 0x66, 0xC4, 0x6A, 0x4F, 0xCC, 0x2D, 0x34, 0x98, 0x43, 0x26, 0xAC, 0xA6, 0xC9, 0xAE, 0x20, 0x89, 0x75, 0xD2, 0xE2, 0xF2, 0x86, 0xCA, 0xBB, 0x0C, 0x16, 0x90, 0x1F, 0xA8, 0x06, 0x92, 0xCD, 0xC6, 0x48, 0xB3, 0x7C, 0x51, 0xCE, 0x15, 0xD9, 0xA5, 0x73, 0x18, 0xDF, 0xE1, 0x76, 0xE8, 0xC5, 0x2F, 0xB6, 0xF3, 0xA0, 0x5D, 0x0F, 0xF4, 0x36, 0xFE, 0x30, 0xD7, 0x6A, 0xD0, 0x2E, 0x15, 0x3C, 0xBF, 0x04, 0x6F, 0x28, 0x77, 0xB1, 0xCE, 0x9B, 0xD2, 0x34, 0x58, 0xB4, 0xD5, 0xF3, 0x25, 0xFB, 0x4A, 0x1B, 0xDD, 0xE9, 0xA6, 0x65, 0x9C, 0xDA, 0x54, 0xDE, 0x9D, 0x73, 0xA5, 0xED, 0x98, 0x44, 0x0B, 0x7A, 0xB9, 0x83, 0x6E, 0x66, 0x13, 0x85, 0x94, 0x1A, 0x78, 0xFD, 0xF1, 0x29, 0x40, 0x8F, 0xCF, 0xB3, 0xD4, 0x46, 0xFF, 0x32, 0x42, 0xC3, 0x20, 0x27, 0x8C, 0xCA, 0xC8, 0xCC, 0x10, 0x18, 0xDB, 0x75, 0x9E, 0xE1, 0x88, 0xEE, 0xE7, 0x21, 0x51, 0x95, 0xCB, 0xEA, 0xF8, 0x01, 0xC4, 0x7B, 0x56, 0x39, 0x0A, 0x93, 0x4B, 0x49, 0x2A, 0x50, 0x55, 0xCD, 0xA7, 0x53, 0xB2, 0x60, 0xEC, 0x9F, 0xBC, 0xB6, 0xBA, 0x0C, 0xE8, 0x1E, 0x33, 0x91, 0x67, 0x6D, 0x5A, 0xAA, 0xC2, 0xE3, 0xA4, 0x22, 0x3F, 0x06, 0xF7, 0x89, 0xC0, 0x62, 0x16, 0xF5, 0x4D, 0x5D, 0x1D, 0x3D, 0xFC, 0xB0, 0x3B, 0x90, 0x1C, 0xC7, 0x45, 0x5F, 0x47, 0xF0, 0x80, 0x31, 0x05, 0xA9, 0xD6, 0x68, 0xBE, 0xB7, 0x12, 0x19, 0x87, 0x81, 0xD8, 0x9A, 0x7C, 0xE5, 0x7F, 0xF6, 0x2C, 0x69, 0xDC, 0x00, 0x3A, 0xEF, 0x37, 0x72, 0x2B, 0xE6, 0x5C, 0x38, 0x4E, 0x24, 0x4F, 0x26, 0xAD, 0xFA, 0x14, 0xE0, 0x23, 0x1F, 0xAF, 0xC9, 0x8D, 0x84, 0x76, 0x82, 0xF2, 0x57, 0x3E, 0x6C, 0xD9, 0x4C, 0x2F, 0xC5, 0xAE, 0x71, 0xBD, 0xC1, 0x70, 0x7D, 0x52, 0x0E, 0xA3, 0x35, 0x2D, 0x08, 0x02, 0x5E, 0x8E, 0x41, 0xB5, 0xAC, 0xBB, 0x64, 0xD1, 0x7E, 0xDF, 0xE2, 0x8A, 0xD3, 0x6B, 0x86, 0x03, 0x43, 0x97, 0xB8, 0xAB, 0xC6, 0x17, 0xF9, 0x59, 0xA0, 0x79, 0x48, 0xA8, 0x5B, 0x61, 0x96, 0xE4, 0x0D, 0x63, 0x99, 0xA2, 0xEB, 0x92, 0x11, 0x07, 0x8B, 0xA1, 0x09, 0x74, 0x4E, 0xE0, 0xFA, 0xC9, 0xA7, 0x56, 0x83, 0x4F, 0x62, 0xE5, 0x11, 0xE1, 0x04, 0x64, 0x33, 0xCB, 0xC4, 0x9E, 0x06, 0x0E, 0xDD, 0x1A, 0x32, 0x92, 0x2A, 0x8F, 0xF6, 0x77, 0x6C, 0x54, 0x89, 0xEE, 0xFB, 0x4B, 0x1F, 0x12, 0xB6, 0x67, 0x2E, 0x9B, 0xA5, 0x47, 0x55, 0x5F, 0xA9, 0xA2, 0x0B, 0x52, 0x40, 0xF9, 0x69, 0x72, 0xBF, 0xA4, 0x6F, 0x82, 0x5C, 0x16, 0x6A, 0x98, 0xB4, 0x01, 0x7F, 0xBC, 0x09, 0x1D, 0x9C, 0xD4, 0x76, 0x4D, 0xBD, 0xE9, 0x7D, 0xA8, 0xFF, 0x14, 0xAB, 0x78, 0x61, 0xE4, 0x36, 0x26, 0x51, 0xE7, 0xCE, 0x0C, 0xB2, 0xE2, 0xF1, 0x75, 0x44, 0x1B, 0x71, 0x7B, 0xE6, 0x27, 0x17, 0x0D, 0x42, 0x97, 0xD2, 0xBA, 0xAE, 0x46, 0x22, 0xF0, 0xB0, 0x96, 0xD9, 0x25, 0x74, 0x79, 0x19, 0xC1, 0x50, 0xDE, 0xEA, 0x90, 0x39, 0x57, 0x99, 0x3F, 0x48, 0x31, 0x2B, 0x8B, 0x95, 0x35, 0x18, 0xE3, 0x4C, 0x88, 0x23, 0x6D, 0xD0, 0x1E, 0x94, 0xF3, 0x5B, 0xD7, 0x7E, 0x8A, 0x5A, 0x65, 0xF7, 0xCC, 0x60, 0xB3, 0x68, 0x91, 0xBE, 0x59, 0x8E, 0x43, 0x28, 0x7C, 0xC6, 0xC5, 0x86, 0x63, 0xD6, 0xCD, 0xBB, 0x2F, 0x6E, 0xDB, 0x5E, 0x80, 0x05, 0xFD, 0xA6, 0x7A, 0xDF, 0x08, 0x66, 0x02, 0x8C, 0x41, 0xE8, 0xF5, 0x1C, 0x21, 0x84, 0x70, 0x3D, 0x8D, 0xAD, 0x38, 0xCA, 0x0F, 0x30, 0x29, 0x9F, 0xB8, 0x85, 0xEF, 0x2D, 0xED, 0x2C, 0xEB, 0x3E, 0xC8, 0x10, 0x3C, 0x93, 0xDA, 0x4A, 0x73, 0x9A, 0xB9, 0xDC, 0xB1, 0x13, 0xF8, 0x45, 0xCF, 0xC7, 0xF4, 0x3B, 0xFE, 0x9D, 0xAF, 0xEC, 0xC0, 0xA0, 0x15, 0xC2, 0x87, 0x37, 0x34, 0x00, 0xAA, 0xD8, 0x0A, 0xD3, 0xAC, 0x81, 0x24, 0x3A, 0x53, 0x49, 0xB5, 0xC3, 0xB7, 0xA1, 0xF2, 0x07, 0x58, 0xD1, 0x03, 0xFC, 0x6B, 0xD5, 0xA3, 0x20, 0x5D, 0xD9, 0xC9, 0x1F, 0xD8, 0x6D, 0x30, 0x4C, 0x64, 0x43, 0x3A, 0x99, 0x74, 0x89, 0x27, 0xDE, 0x61, 0x33, 0xFE, 0x08, 0x04, 0xF3, 0xEB, 0x58, 0xC2, 0x7D, 0x87, 0x37, 0xDA, 0xAB, 0xD0, 0xEA, 0x35, 0xFD, 0x62, 0x7C, 0x79, 0x60, 0x50, 0x5D, 0x16, 0x95, 0xF6, 0xED, 0x70, 0x1C, 0xCD, 0xC7, 0xBA, 0x77, 0x9A, 0xB6, 0x07, 0x11, 0x66, 0xFB, 0x13, 0x3B, 0x2F, 0xF9, 0xF5, 0x24, 0xBF, 0x00, 0xEE, 0x78, 0x31, 0xAF, 0x5B, 0x7E, 0xE8, 0xF2, 0x9D, 0xCC, 0x1D, 0xC8, 0xC5, 0x8A, 0x34, 0x2E, 0x42, 0xC1, 0x47, 0x6A, 0xDB, 0xB5, 0x38, 0x23, 0x85, 0x8E, 0x48, 0x44, 0xD3, 0x52, 0xAC, 0x57, 0x0D, 0xC3, 0xD7, 0x63, 0xAE, 0x28, 0x32, 0x49, 0x01, 0x20, 0xA4, 0xCE, 0xB1, 0xDD, 0x5C, 0x6B, 0x4F, 0xC4, 0x2D, 0x9F, 0x94, 0x1E, 0x6C, 0xA6, 0xE4, 0xF1, 0x25, 0x76, 0x45, 0x0E, 0xD4, 0x82, 0x68, 0x59, 0xFF, 0xC0, 0x22, 0x4D, 0x72, 0x53, 0xE2, 0x36, 0x4E, 0x69, 0x81, 0xB7, 0x3E, 0x0C, 0x9C, 0x1B, 0xFA, 0x56, 0x86, 0x9B, 0x5A, 0xA8, 0xA9, 0xBE, 0xAA, 0x21, 0x14, 0xE7, 0x6E, 0x55, 0xD2, 0xE9, 0xE6, 0x75, 0x15, 0x93, 0x5F, 0xDF, 0x4A, 0xF8, 0xB0, 0x3C, 0xBC, 0xD1, 0xA5, 0x73, 0x54, 0x5E, 0x40, 0x8C, 0x7B, 0xF7, 0xA2, 0xEF, 0x19, 0xB2, 0x9E, 0xA3, 0x8B, 0x46, 0x0F, 0xEC, 0x6F, 0x12, 0x10, 0x0B, 0x7F, 0x0A, 0x83, 0x41, 0xB3, 0x90, 0xCB, 0x1A, 0x88, 0x2C, 0xF4, 0xCA, 0x09, 0xCF, 0x91, 0x4B, 0xF0, 0x39, 0x80, 0x26, 0x96, 0xFC, 0x03, 0x2B, 0x18, 0x2A, 0x06, 0xC6, 0x02, 0xE5, 0x65, 0xBD, 0x51, 0xB4, 0xBB, 0xD6, 0x05, 0xDC, 0x97, 0x98, 0x3F, 0xE3, 0x17, 0xB9, 0xE0, 0xA1, 0x3D, 0xE1, 0xAD, 0x8D, 0x29, 0x8F, 0x67, 0xA0, 0x84, 0xB8, 0x92, 0xD5, 0x71, 0x7A, 0xA7 }; + public static readonly byte[] GI_CBXExpansionKey = new byte[] { 0x3C, 0x5E, 0xAD, 0x0F, 0xD5, 0x09, 0x27, 0x3F, 0xB8, 0x70, 0x00, 0x9A, 0xCD, 0x30, 0x1B, 0xEB, 0xB7, 0x04, 0x71, 0xD9, 0x39, 0x80, 0x21, 0x29, 0xB5, 0xCC, 0x7A, 0xB2, 0xAE, 0xB6, 0x75, 0x14, 0x63, 0x2A, 0x82, 0x34, 0x70, 0xA5, 0x40, 0xEB, 0xF9, 0x4E, 0x95, 0x1C, 0x0A, 0xA4, 0xD0, 0xF6, 0x56, 0x1E, 0x0E, 0xE3, 0x7B, 0xBF, 0x0D, 0xC5, 0xD3, 0x04, 0xF3, 0x43, 0xDA, 0x76, 0x37, 0xDD, 0xAD, 0xE9, 0xF6, 0x97, 0x54, 0xD2, 0x56, 0xA2, 0x00, 0xBE, 0x96, 0xD0, 0x61, 0x4F, 0x8A, 0xBE, 0x5C, 0x32, 0x74, 0xC8, 0xFD, 0x7F, 0x2C, 0xFC, 0x5D, 0x4E, 0xD0, 0x6B, 0x2A, 0x2B, 0xF8, 0xDE, 0x12, 0x5B, 0xA2, 0x58, 0x8C, 0x4E, 0x02, 0xE5, 0x3C, 0xA6, 0xDB, 0x02, 0xBF, 0xAA, 0xE5, 0x12, 0xE0, 0xEF, 0x09, 0x36, 0xF6, 0xA0, 0xE5, 0x60, 0xE1, 0x62, 0xE4, 0x54, 0x02, 0xA7, 0xD1, 0x71, 0xC0, 0xF6, 0xE0, 0xFF, 0xDD, 0x01, 0xBA, 0xD5, 0x26, 0x94, 0x2D, 0x85, 0xA3, 0x7D, 0xDF, 0x0F, 0x94, 0x2F, 0xD6, 0x39, 0xE6, 0xEC, 0xCA, 0x86, 0x73, 0xD5, 0x66, 0x6A, 0x98, 0x92, 0x86, 0xCE, 0x20, 0xB4, 0xF0, 0x4C, 0xAA, 0xDD, 0x5A, 0xD5, 0x78, 0x2C, 0x81, 0xBE, 0xAE, 0x3A, 0x31, 0x14 }; + public static readonly byte[] GI_CBXInitVector = new byte[] { 0xA2, 0x25, 0x25, 0x99, 0xB7, 0x62, 0xF4, 0x39, 0x28, 0xE1, 0xB7, 0x73, 0x91, 0x05, 0x25, 0x87 }; + public static readonly byte[] GI_CBXMhy0ShiftRow = new byte[] { 0x0D, 0x0E, 0x05, 0x0A, 0x00, 0x04, 0x0C, 0x0B, 0x06, 0x02, 0x03, 0x08, 0x0F, 0x01, 0x07, 0x09, 0x00, 0x0B, 0x09, 0x03, 0x08, 0x07, 0x05, 0x02, 0x0A, 0x0F, 0x01, 0x06, 0x0D, 0x04, 0x0C, 0x0E, 0x04, 0x0F, 0x0D, 0x07, 0x0C, 0x02, 0x05, 0x01, 0x09, 0x06, 0x0A, 0x00, 0x03, 0x08, 0x0B, 0x0E }; + public static readonly byte[] GI_CBXMhy0Key = new byte[] { 0x69, 0xB0, 0x8C, 0x21, 0xDC, 0x23, 0x3D, 0x9B }; + public static readonly byte[] GI_CBXMhy0Mul = new byte[] { 0x47, 0x0C, 0xF7, 0x6E, 0x9D, 0xF1, 0xBB, 0x88 }; + public static readonly ulong GI_CBXInitSeed = 0xCEAC3B5A867837AC; + #endregion + + #region Pack + public static readonly byte[] PackExpansionKey = new byte[] { 0x3C, 0x5E, 0xAD, 0x0F, 0xD5, 0x09, 0x27, 0x3F, 0xB8, 0x70, 0x00, 0x9A, 0xCD, 0x30, 0x1B, 0xEB, 0xB7, 0x04, 0x71, 0xD9, 0x39, 0x80, 0x21, 0x29, 0xB5, 0xCC, 0x7A, 0xB2, 0xAE, 0xB6, 0x75, 0x14, 0x63, 0x2A, 0x82, 0x34, 0x70, 0xA5, 0x40, 0xEB, 0xF9, 0x4E, 0x95, 0x1C, 0x0A, 0xA4, 0xD0, 0xF6, 0x56, 0x1E, 0x0E, 0xE3, 0x7B, 0xBF, 0x0D, 0xC5, 0xD3, 0x04, 0xF3, 0x43, 0xDA, 0x76, 0x37, 0xDD, 0xAD, 0xE9, 0xF6, 0x97, 0x54, 0xD2, 0x56, 0xA2, 0x00, 0xBE, 0x96, 0xD0, 0x61, 0x4F, 0x8A, 0xBE, 0x5C, 0x32, 0x74, 0xC8, 0xFD, 0x7F, 0x2C, 0xFC, 0x5D, 0x4E, 0xD0, 0x6B, 0x2A, 0x2B, 0xF8, 0xDE, 0x12, 0x5B, 0xA2, 0x58, 0x8C, 0x4E, 0x02, 0xE5, 0x3C, 0xA6, 0xDB, 0x02, 0xBF, 0xAA, 0xE5, 0x12, 0xE0, 0xEF, 0x09, 0x36, 0xF6, 0xA0, 0xE5, 0x60, 0xE1, 0x62, 0xE4, 0x54, 0x02, 0xA7, 0xD1, 0x71, 0xC0, 0xF6, 0xE0, 0xFF, 0xDD, 0x01, 0xBA, 0xD5, 0x26, 0x94, 0x2D, 0x85, 0xA3, 0x7D, 0xDF, 0x0F, 0x94, 0x2F, 0xD6, 0x39, 0xE6, 0xEC, 0xCA, 0x86, 0x73, 0xD5, 0x66, 0x6A, 0x98, 0x92, 0x86, 0xCE, 0xC5, 0x24, 0x91, 0x5A, 0x4F, 0x4D, 0x3B, 0xC3, 0x9D, 0xBC, 0xE0, 0xA8, 0x4B, 0xAA, 0x50, 0x02 }; + public static readonly byte[] PackBlockKey = new byte[] { 0x5B, 0xF5, 0x87, 0x75, 0x53, 0x7F, 0xE6, 0x07, 0x36, 0x71, 0xCD, 0xF6, 0x54, 0x3F, 0x33, 0xEB, 0xC3, 0x23, 0xFE, 0x8F, 0x40, 0xC9, 0x91, 0xC3, 0xF0, 0x0C, 0x02, 0x43, 0xC4, 0xFA, 0xA5, 0x42, 0x87, 0xA0, 0x2D, 0x89, 0xB2, 0xC0, 0x24, 0x95, 0x67, 0x98, 0xE1, 0xB8, 0x3D, 0x5D, 0xF9, 0xD9, 0x05, 0xB3, 0x42, 0xE5, 0x0C, 0x18, 0x26, 0xE2, 0xD8, 0x0E, 0x86, 0x72, 0x68, 0xAA, 0xD5, 0x1B, 0x50, 0xCF, 0xA3, 0xC5, 0xBF, 0xFC, 0xCF, 0xA9, 0x27, 0x59, 0x6E, 0x74, 0xA6, 0x3B, 0xB1, 0x17, 0x75, 0x3E, 0x8A, 0x86, 0x1C, 0x1A, 0xCA, 0xED, 0xBC, 0x27, 0xB2, 0x72, 0x9A, 0x2C, 0x47, 0xA1, 0x8A, 0x7D, 0xFF, 0x3A, 0x25, 0x03, 0xD5, 0x79, 0x03, 0x4B, 0x3D, 0xA0, 0x1F, 0x47, 0x96, 0xB5, 0x0E, 0x59, 0xF3, 0x13, 0x80, 0x2A, 0xC8, 0x8A, 0xEA, 0xA3, 0x4D, 0xDE, 0xFD, 0xF5, 0x09, 0x96, 0x18, 0xA3, 0x51, 0x18, 0x2C, 0x05, 0x62, 0xF2, 0x07, 0x3B, 0x00, 0x92, 0x95, 0x9F, 0x8F, 0x81, 0x09, 0x17, 0x79, 0x07, 0xED, 0x8E, 0xF2, 0x84, 0xDE, 0xD3, 0x61, 0x24, 0x57, 0xD8, 0x94, 0x38, 0x77, 0xAB, 0x8B, 0x86, 0x24, 0xD8, 0x45, 0xD5, 0xF7, 0x90, 0x50, 0x86, 0x7B, 0x30, 0x5B, 0x0A, 0x59, 0x67, 0x23, 0x4D, 0x4A, 0x14, 0xE1, 0x61, 0x5B, 0x28, 0xB9, 0xEF, 0x1B, 0x06, 0x73, 0x9E, 0xBB, 0x6F, 0xD2, 0x81, 0x75, 0x63, 0x06, 0x97, 0x2A, 0xE0, 0xF3, 0x83, 0xC4, 0x9D, 0x4E, 0x3C, 0x99, 0x1D, 0xDD, 0xF1, 0x51, 0x64, 0x1E, 0x6A, 0x77, 0x0E, 0x05, 0x86, 0xE4, 0x01, 0xCE, 0x09, 0x45, 0x0E, 0xB1, 0xB2, 0x87, 0x8F, 0xF9, 0x4A, 0xEE, 0x37, 0xCD, 0x41, 0xB6, 0x11, 0xDC, 0x7A, 0xB0, 0xE3, 0x40, 0x31, 0xEF, 0x2C, 0x64, 0x92, 0x30, 0x31, 0x5B, 0x56, 0x36, 0x3C, 0xEF, 0xDA, 0x3E, 0x72, 0x8E, 0xA9, 0x7E, 0x1C, 0xDE, 0xF6, 0x01, 0x52, 0x8F, 0x5C, 0xF0, 0x0A, 0x05, 0x23, 0xD1, 0xEA, 0xC2, 0x56, 0x6F, 0x99, 0x20, 0x63, 0xEF, 0x4B, 0x9B, 0x14, 0x72, 0x6D, 0x24, 0x02, 0xB3, 0x4B, 0x5F, 0x9B, 0xB0, 0x0A, 0x60, 0x7F, 0x87, 0xA4, 0x86, 0xF7, 0x08, 0xD8, 0xFF, 0x4D, 0xBF, 0xA2, 0x7A, 0x63, 0x69, 0x8E, 0x83, 0x85, 0x2B, 0xE6, 0x02, 0x71, 0x1F, 0x28, 0x3F, 0x07, 0xBB, 0xBD, 0xB3, 0xE4, 0x06, 0x3C, 0x91, 0x52, 0x33, 0x08, 0x89, 0x3D, 0xA5, 0xEC, 0x16, 0x69, 0x4C, 0xAC, 0xD7, 0xA6, 0xA4, 0x16, 0x37, 0x1A, 0x77, 0x34, 0x48, 0xDF, 0x3E, 0x9D, 0x3A, 0x4E, 0xB7, 0x85, 0x9B, 0x3F, 0x02, 0xFA, 0xB2, 0xD7, 0x42, 0xE2, 0x72, 0xBB, 0xC4, 0x14, 0x1C, 0x55, 0xEA, 0x69, 0x6F, 0x45, 0x76, 0x1B, 0x5D, 0xB2, 0x56, 0xF6, 0xA0, 0xE9, 0xED, 0x53, 0xB7, 0x69, 0x32, 0x05, 0xBC, 0xDC, 0xEA, 0xE5, 0xD1, 0xF5, 0x59, 0xF9, 0xB2, 0x63, 0x7D, 0x86, 0xD1, 0x66, 0xF6, 0x15, 0x51, 0xC7, 0x91, 0xBF, 0xAA, 0x76, 0x51, 0x9A, 0x71, 0x31, 0xB5, 0x90, 0x18, 0xA7, 0x4F, 0x66, 0xA7, 0x4D, 0x17, 0x64, 0xE5, 0x86, 0xBE, 0xBD, 0xD5, 0x4F, 0x9A, 0x8F, 0xBE, 0x9F, 0x29, 0xE7, 0x3B, 0xB2, 0x54, 0x88, 0x7D, 0x7F, 0xAC, 0x03, 0xD5, 0x7D, 0x73, 0x63, 0x7B, 0x72, 0x78, 0x4B, 0x21, 0xD0, 0xA0, 0x08, 0x6F, 0xBA, 0xE1, 0xFA, 0x69, 0x72, 0x4C, 0x51, 0x60, 0xAB, 0xEE, 0xBD, 0x9A, 0x10, 0x81, 0x8D, 0xAE, 0x86, 0xEB, 0x18, 0x90, 0x5E, 0x7B, 0x27, 0x32, 0xAF, 0x00, 0xF5, 0xA4, 0xBD, 0x58, 0x0F, 0x16, 0xE4, 0x64, 0xD8, 0x8D, 0xE4, 0x83, 0x7B, 0x9A, 0x2B, 0xE1, 0xA1, 0xEC, 0xFD, 0x3B, 0xEF, 0x5C, 0x2A, 0x26, 0x4E, 0x56, 0x91, 0x04, 0x76, 0x4E, 0xF6, 0x2C, 0x37, 0x4E, 0xFA, 0xF6, 0xE5, 0x97, 0x54, 0x1D, 0x40, 0x26, 0xF7, 0x2B, 0xDD, 0x40, 0x9B, 0x7C, 0xEF, 0x7B, 0x18, 0x98, 0x6C, 0xBB, 0x03, 0x56, 0x7F, 0x60, 0xD8, 0xDA, 0x81, 0x74, 0xB2, 0x3C, 0x97, 0x20, 0x5F, 0xC8, 0x2E, 0xE9, 0xC5, 0xEA, 0x34, 0x77, 0xD3, 0xEF, 0x83, 0xBB, 0x8A, 0x62, 0x0E, 0xB8, 0xAA, 0xFD, 0x73, 0x6A, 0xB7, 0x02, 0xDB, 0xAC, 0x41, 0xB2, 0xF1, 0x02, 0xBF, 0x48, 0x0C, 0x1D, 0x14, 0x50, 0xC9, 0x28, 0x28, 0xCC, 0x19, 0x80, 0x02, 0xF7, 0x31, 0xD1, 0x51, 0x16, 0x02, 0xD9, 0x02, 0x2A, 0x6F, 0x71, 0x44, 0x05, 0xC5, 0x2C, 0xFA, 0x52, 0x2B, 0x77, 0x10, 0x95, 0x35, 0xB0, 0x5C, 0x67, 0x03, 0x42, 0x72, 0x51, 0x06, 0x7C, 0xBF, 0x8E, 0xDE, 0xA0, 0x20, 0xA8, 0x32, 0xEA, 0x7C, 0x62, 0x18, 0x2A, 0x58, 0x4F, 0x8C, 0xE8, 0x29, 0x2F, 0x4C, 0x5C, 0x9D, 0xCD, 0x15, 0x8A, 0x92, 0x00, 0x89, 0xAA, 0x5F, 0x10, 0x85, 0x5A, 0xE1, 0xDB, 0xBB, 0x9C, 0x71, 0x06, 0xCC, 0xF8, 0x18, 0x78, 0x09, 0x52, 0x13, 0x38, 0xB3, 0xFA, 0x23, 0x1C, 0x5D, 0x23, 0x58, 0x63, 0xA3, 0xE4, 0x37, 0x56, 0xBA, 0xD2, 0xAC, 0x86, 0x81, 0x70, 0x75, 0x9B, 0xC2, 0xEA, 0x82, 0x57, 0xC0, 0x82, 0x6F, 0x0C, 0x82, 0x48, 0x1B, 0x9E, 0xB3, 0xEA, 0x06, 0xA1, 0xBA, 0x6B, 0xC9, 0xC0, 0x50, 0x50, 0x6E, 0x41, 0x8E, 0xB6, 0xC0, 0x8E, 0xA5, 0xE7, 0xC7, 0x4D, 0xBD, 0x7A, 0x04, 0x81, 0x57, 0x08, 0x1D, 0xC3, 0xB4, 0x79, 0x41, 0x16, 0xC2, 0x00, 0x86, 0xEF, 0x48, 0x07, 0x4F, 0x60, 0xAC, 0xEB, 0x91, 0x5B, 0x5F, 0x84, 0x36, 0x75, 0xB3, 0xAE, 0x94, 0x12, 0xE6, 0xAF, 0x53, 0x80, 0x20, 0xDA, 0x28, 0x8D, 0x7D, 0x23, 0xA2, 0xF7, 0x56, 0xAD, 0xF9, 0x4C, 0x45, 0xF6, 0xC7, 0x8A, 0x78, 0xCE, 0xE7, 0x3D, 0xAA, 0xC9, 0x8B, 0x70, 0x53, 0x64, 0xEE, 0x2E, 0x3B, 0xED, 0xFB, 0x77, 0x61, 0xF8, 0x85, 0x4B, 0xFF, 0xA7, 0x20, 0x5F, 0x9B, 0x6E, 0x9D, 0x70, 0x9A, 0x56, 0x2A, 0xD3, 0xB3, 0xD0, 0xD4, 0x11, 0x9B, 0x36, 0xA8, 0x71, 0x6A, 0x95, 0x3C, 0xDD, 0x98, 0x8F, 0x04, 0x81, 0x8D, 0x78, 0x4C, 0xE0, 0x3A, 0x0F, 0x0F, 0xC0, 0xE2, 0x80, 0xC4, 0xEA, 0x40, 0xC7, 0x4F, 0x52, 0x8F, 0x73, 0x05, 0x5D, 0x53, 0xB0, 0x86, 0x8B, 0x8D, 0x64, 0xBD, 0x3B, 0xBA, 0xAD, 0x15, 0x59, 0xB2, 0x81, 0x36, 0x8B, 0xD5, 0x7B, 0xC9, 0xD6, 0x17, 0xEB, 0x7C, 0xA1, 0xEF, 0x1E, 0xC8, 0x40, 0xA7, 0x94, 0x73, 0x20, 0xB8, 0x4B, 0x8C, 0x23, 0xD7, 0x4A, 0x4B, 0x44, 0x5A, 0xB7, 0x61, 0xD1, 0xDC, 0xDB, 0xB7, 0x7C, 0xBF, 0x10, 0xA0, 0x0D, 0x5D, 0x98, 0xE6, 0x1B, 0x47, 0xCF, 0x99, 0x20, 0xC5, 0xBF, 0x02, 0x46, 0x5C, 0xE2, 0x1D, 0x8B, 0x86, 0x07, 0x1A, 0x6A, 0xFC, 0x2F, 0x98, 0x7F, 0xF4, 0x2A, 0xF8, 0x4C, 0x70, 0x9C, 0x49, 0x1C, 0x7E, 0xB3, 0x9E, 0x98, 0x02, 0x35, 0xE0, 0xC0, 0x9B, 0x63, 0xED, 0x52, 0x8D, 0x5A, 0x25, 0xF9, 0x36, 0xD1, 0x2C, 0x19, 0x8E, 0xE2, 0xA1, 0x82, 0x25, 0xAC, 0x7D, 0x52, 0x9D, 0xF1, 0x47, 0x77, 0xCE, 0x5E, 0x4F, 0x4F, 0x26, 0xE5, 0x36, 0xDB, 0xE5, 0x76, 0x03, 0x0B, 0x99, 0x5C, 0xE5, 0x9E, 0x20, 0x7E, 0xB4, 0xAD, 0xF6, 0xA6, 0xC4, 0x6A, 0x99, 0x11, 0x54, 0x75, 0x3D, 0x70, 0x77, 0xDF, 0x41, 0xEC, 0x0C, 0x6B, 0x9D, 0xB6, 0x1C, 0xA1, 0x7D, 0xF1, 0x6B, 0xF1, 0xF6, 0x58, 0x73, 0x56, 0xC6, 0x93, 0x58, 0xE0, 0xD6, 0xCD, 0x74, 0x07, 0xDD, 0xB6, 0xE4, 0x15, 0x97, 0x32, 0x02, 0x6E, 0x71, 0x8A, 0x1A, 0x4C, 0x9F, 0xFA, 0x61 }; + #endregion + + #region BH3 + public static readonly byte[] BH3BlockKey = new byte[] { 0x8B, 0xD8, 0xD8, 0x92, 0xB6, 0x54, 0xB5, 0xCC, 0xBA, 0x8B, 0x35, 0x0F, 0x3C, 0x86, 0x97, 0x2B, 0x6C, 0x29, 0x21, 0x23, 0xB1, 0x32, 0x86, 0x00, 0x9C, 0x59, 0xED, 0x30, 0x49, 0xEA, 0xA4, 0x34, 0x8B, 0x65, 0x79, 0x98, 0xBB, 0x91, 0xD4, 0x90, 0xA8, 0xBB, 0x14, 0xB3, 0x4B, 0xF2, 0x24, 0x0B, 0x86, 0xF5, 0x1B, 0x42, 0xBB, 0x32, 0x44, 0xD5, 0xA8, 0xD2, 0x0F, 0x33, 0x16, 0xF3, 0x80, 0x7A, 0x46, 0x1B, 0xC7, 0x8F, 0x06, 0xD2, 0xE3, 0xC0, 0x36, 0x1B, 0x6E, 0x30, 0x10, 0x98, 0xC8, 0x21, 0x08, 0x56, 0x75, 0x76, 0x9D, 0xA1, 0xE7, 0xF8, 0xF4, 0x5F, 0x6E, 0xB3, 0x71, 0xE4, 0xB9, 0x43, 0x44, 0xC1, 0x7A, 0x00, 0xF8, 0x77, 0x20, 0x2B, 0x06, 0x6B, 0xED, 0x3F, 0xE9, 0x74, 0x13, 0x6E, 0xA5, 0x61, 0x2B, 0x1E, 0x45, 0x9C, 0x74, 0xB9, 0x82, 0x22, 0x9F, 0x32, 0xBC, 0xEF, 0x9B, 0x88, 0x5A, 0x9E, 0x55, 0xCC, 0xE5, 0xB5, 0xA2, 0x6A, 0x01, 0xEF, 0xEC, 0x13, 0xCF, 0x3E, 0x4F, 0x7C, 0xA0, 0xF8, 0x91, 0xE6, 0x70, 0x6D, 0x4B, 0xDD, 0xEC, 0x24, 0x14, 0x7B, 0x97, 0x23, 0x00, 0x93, 0x0F, 0xCE, 0xB6, 0x38, 0xB5, 0xB6, 0xB0, 0x95, 0x4E, 0x0E, 0x07, 0xE0, 0xEE, 0x6D, 0x0E, 0xDC, 0xB2, 0x3D, 0xC9, 0x7A, 0xA5, 0x41, 0xB2, 0x02, 0xAD, 0xDE, 0x72, 0x10, 0x65, 0xCC, 0x7A, 0x7E, 0xCC, 0xD0, 0x69, 0xC6, 0xA7, 0xB2, 0xB6, 0x38, 0x76, 0x55, 0x6B, 0xA0, 0xAD, 0xF1, 0xEF, 0xA0, 0x9D, 0xCF, 0x2E, 0x89, 0x07, 0x64, 0x6F, 0x1D, 0xE0, 0x51, 0x43, 0xB3, 0x4C, 0x15, 0x65, 0x71, 0x76, 0xFD, 0x1E, 0x0A, 0xA3, 0x00, 0x18, 0x36, 0x12, 0xB0, 0xFB, 0x31, 0xCE, 0x22, 0x2D, 0xD4, 0xFD, 0x09, 0x1D, 0x1A, 0x99, 0x19, 0xFA, 0x02, 0x48, 0x4D, 0xC8, 0x42, 0xA1, 0x2B, 0x8D, 0xA6, 0xF2, 0x53, 0x19, 0x92, 0x57, 0x67, 0xBD, 0xB2, 0x90, 0xE6, 0x01, 0x36, 0xEE, 0x99, 0x1D, 0xC6, 0x30, 0xA0, 0x41, 0xFE, 0xAC, 0x06, 0xC0, 0x56, 0xEE, 0xF4, 0xB8, 0x31, 0xDF, 0xDE, 0xE6, 0x9E, 0x6E, 0x61, 0x42, 0x59, 0xD6, 0x99, 0x0F, 0x87, 0x1E, 0xDD, 0x9D, 0xB5, 0xCA, 0xBC, 0xF9, 0x82, 0xE2, 0x27, 0xD2, 0x2C, 0x5E, 0x51, 0xD8, 0x11, 0x17, 0x4A, 0x32, 0xA3, 0x6E, 0xCB, 0x33, 0xEE, 0x00, 0xC2, 0x22, 0xF8, 0x2C, 0x7E, 0x52, 0x0B, 0xB8, 0x84, 0x83, 0xD7, 0x65, 0x5A, 0x18, 0x4F, 0xB9, 0x54, 0x26, 0x05, 0x02, 0x4D, 0x52, 0x65, 0xAA, 0x03, 0x30, 0x16, 0x45, 0x43, 0x41, 0xDC, 0xBA, 0x75, 0xBD, 0xF2, 0x23, 0xCB, 0xF5, 0x32, 0xE6, 0x41, 0xEC, 0x06, 0x09, 0x86, 0xC2, 0x2C, 0xC0, 0xD7, 0x09, 0xE7, 0xA2, 0xE3, 0x61, 0xFC, 0x10, 0x03, 0x96, 0xF2, 0x3D, 0x31, 0x97, 0x0F, 0x0B, 0x3C, 0x64, 0x9D, 0xC8, 0x72, 0x1C, 0xF5, 0x6B, 0x9A, 0x13, 0x0D, 0xED, 0x0E, 0xB0, 0xFE, 0x4E, 0x48, 0x51, 0x38, 0x90, 0x01, 0x60, 0x61, 0xF3, 0x10, 0x98, 0xFB, 0xDF, 0x13, 0x76, 0x3A, 0x70, 0x6F, 0x1E, 0x05, 0x13, 0xB1, 0x77, 0x8F, 0xDF, 0x37, 0xA3, 0x96, 0xFD, 0xFA, 0x05, 0xFE, 0x6E, 0xAA, 0xBB, 0x12, 0x12, 0xE6, 0x89, 0xAD, 0xCA, 0x20, 0x0D, 0x4C, 0x35, 0x08, 0xFF, 0xC7, 0x92, 0x68, 0x9D, 0x5B, 0xAC, 0x38, 0xA2, 0x7C, 0x04, 0x2B, 0x2F, 0x02, 0x99, 0x81, 0x17, 0x97, 0xC4, 0x92, 0xF7, 0xD8, 0x6F, 0xCE, 0x91, 0x6F, 0x71, 0x5F, 0x31, 0xB4, 0x2F, 0xCC, 0x14, 0x64, 0xA4, 0x32, 0xC0, 0xE5, 0xF1, 0xA0, 0x34, 0xBD, 0x60, 0x87, 0x9A, 0x12, 0x2B, 0x2C, 0xCC, 0x83, 0xEE, 0x99, 0x4A, 0x3E, 0x5A, 0xB5, 0x94, 0x3F, 0xD1, 0x3C, 0x50, 0xB9, 0xAF, 0x1F, 0xFF, 0x8B, 0xB0, 0xAE, 0xF7, 0xC4, 0x1A, 0xFE, 0x8A, 0x95, 0x25, 0x72, 0xAA, 0x23, 0x88, 0x49, 0x98, 0xB3, 0x1D, 0x28, 0x6C, 0xC6, 0x8B, 0xA9, 0x47, 0x33, 0x65, 0xAE, 0xFA, 0x1F, 0xBF, 0x72, 0x2F, 0x0D, 0xBF, 0x33, 0xB4, 0x4B, 0x33, 0x65, 0x08, 0xD6, 0x17, 0x35, 0x8F, 0x75, 0xC9, 0xDF, 0xF4, 0xB7, 0xC2, 0x1A, 0x8F, 0x4D, 0x06, 0x5F, 0x22, 0x2C, 0x62, 0x2E, 0x80, 0x92, 0x9F, 0xF5, 0xF5, 0x09, 0xFA, 0xEE, 0xDB, 0x52, 0xBD, 0x8E, 0x6B, 0x6B, 0x68, 0xD1, 0xBF, 0xFD, 0x9B, 0x51, 0xF6, 0x2B, 0xEC, 0xE4, 0x8C, 0x1D, 0x36, 0x21, 0xCA, 0x08, 0x50, 0x4D, 0x3A, 0xE1, 0x6B, 0x0F, 0x75, 0xC7, 0xC9, 0xC8, 0x76, 0xA1, 0x7D, 0xCD, 0xCD, 0x91, 0x20, 0x65, 0xE6, 0x5E, 0xD9, 0x1A, 0x1A, 0xBD, 0xA5, 0x5D, 0xB9, 0xEA, 0x9D, 0x09, 0xC3, 0x80, 0x45, 0xAD, 0x29, 0x25, 0x4A, 0xAC, 0x9B, 0xFF, 0xBF, 0x43, 0xFC, 0x95, 0x9F, 0x58, 0x66, 0xDB, 0x30, 0xB6, 0xDD, 0x16, 0x3D, 0x18, 0xC2, 0x6B, 0x3D, 0xDB, 0xC0, 0xDC, 0xFC, 0x13, 0xF8, 0x6A, 0xF3, 0x4B, 0x7D, 0x27, 0x14, 0xE7, 0xE5, 0xE5, 0xC2, 0xDF, 0xE6, 0xB3, 0x54, 0xCD, 0x89, 0x30, 0xE3, 0x91, 0x2F, 0xEE, 0x61, 0x9D, 0x60, 0x06, 0xC6, 0x8F, 0x32, 0x74, 0x99, 0x18, 0x44, 0xF8, 0xFE, 0xD8, 0xED, 0xC5, 0x55, 0x29, 0x2C, 0x94, 0x90, 0x96, 0x3E, 0x3D, 0x3C, 0x56, 0xDB, 0xC1, 0xD5, 0xEC, 0x86, 0xFF, 0x86, 0x71, 0xCE, 0xFE, 0x59, 0xC2, 0x33, 0x89, 0x6D, 0xF3, 0x46, 0x88, 0x53, 0xA6, 0xF7, 0x8A, 0x57, 0xF8, 0x0D, 0x1A, 0xD6, 0x8C, 0xD7, 0x44, 0xAF, 0xC6, 0xFF, 0x1E, 0x98, 0x6B, 0xE3, 0x0A, 0xBA, 0x87, 0xEA, 0x02, 0xA9, 0x97, 0x2D, 0x5E, 0x16, 0x81, 0x99, 0xBA, 0xD7, 0x82, 0x5F, 0xCC, 0x1A, 0xDB, 0x79, 0xAB, 0xAD, 0xB4, 0x1F, 0x48, 0x46, 0xCD, 0x06, 0x95, 0xF1, 0xFB, 0x2F, 0xA4, 0x82, 0x03, 0x2B, 0x07, 0xF0, 0x84, 0xEF, 0x93, 0xE7, 0x27, 0x0D, 0xA6, 0x25, 0x02, 0x5E, 0xC2, 0x07, 0xAE, 0x9C, 0xDA, 0x36, 0x03, 0x48, 0xB3, 0x4A, 0xE3, 0x85, 0x8C, 0x60, 0x9E, 0x7D, 0x8E, 0x1C, 0x04, 0x23, 0xE6, 0xD1, 0xCE, 0x3E, 0x89, 0xEA, 0x75, 0xA6, 0xF0, 0x26, 0x3D, 0xD2, 0x84, 0x30, 0x75, 0x8B, 0xD2, 0xA4, 0x76, 0x79, 0x7A, 0x3A, 0x5A, 0x4B, 0xEC, 0xE7, 0x88, 0xC7, 0xCA, 0x9B, 0x65, 0x79, 0xDF, 0x04, 0x56, 0xD1, 0x42, 0x69, 0x04, 0xAB, 0xA7, 0xC1, 0x21, 0xE4, 0x74, 0xA1, 0x6E, 0x9D, 0x0D, 0x75, 0x68, 0x81, 0x58, 0x58, 0x62, 0x9C, 0x68, 0x99, 0xC2, 0xB2, 0x0E, 0x2A, 0x66, 0xD0, 0x01, 0xB2, 0x26, 0xA3, 0x60, 0x4F, 0xBB, 0x53, 0xE3, 0xDC, 0x63, 0xC0, 0xB2, 0x50, 0xFF, 0x55, 0x39, 0x1D, 0x70, 0x82, 0x22, 0xE1, 0xEB, 0x6C, 0x98, 0x52, 0xC2, 0xE1, 0xC4, 0xB7, 0x76, 0x7C, 0x0D, 0xA4, 0xB4, 0xD7, 0x64, 0x44, 0x9F, 0xE2, 0xA5, 0xCC, 0x24, 0x64, 0x9E, 0x67, 0x9D, 0xAA, 0x1D, 0xE5, 0x9F, 0x4A, 0x47, 0x3F, 0x7F, 0x76, 0x30, 0xA9, 0xEE, 0xC7, 0xFA, 0xAA, 0xAA, 0xB2, 0x33, 0x3E, 0x0E, 0x26, 0x8A, 0xA3, 0xC9, 0x03, 0x41, 0x2A, 0xF2, 0xEA, 0x21, 0xE5, 0xE1, 0x59, 0xCA, 0xDD, 0xF1, 0x74, 0x15, 0xB5, 0xC4, 0xED, 0x96, 0x7E, 0x52, 0xA5, 0xCF, 0x0E, 0x3F, 0xDE, 0x0D, 0x39, 0x19, 0x67, 0x99, 0x04, 0xC1, 0x45, 0x21, 0x20, 0xCA, 0x57, 0x9B, 0x29, 0x0F, 0x79, 0xED, 0xC2, 0xB9, 0xBF, 0x29, 0xA2, 0xCA, 0x30, 0xF9, 0xE6, 0x09, 0xAB, 0x58, 0x11, 0x63, 0x15, 0x18, 0xD3, 0x18, 0xFF, 0xF6, 0xD5, 0x23, 0xCC, 0x91, 0x96, 0x25, 0x40, 0x35, 0xDA, 0x4D, 0xB6, 0x85 }; + public static readonly byte[] BH3SBox = new byte[] { 0x75, 0x45, 0xC7, 0x35, 0x7E, 0x7B, 0x46, 0x29, 0xE7, 0x10, 0xC1, 0xEB, 0x52, 0xCA, 0xC2, 0xA0, 0x0D, 0xCC, 0x31, 0xA7, 0xA8, 0x44, 0x07, 0x4C, 0x93, 0x6E, 0xFC, 0x0E, 0xF9, 0xFB, 0xDD, 0xAA, 0x4A, 0x84, 0x18, 0xD9, 0x2C, 0x09, 0x21, 0x13, 0x15, 0xBB, 0x37, 0x8E, 0xE2, 0x77, 0x60, 0x22, 0xE8, 0x06, 0x00, 0xA3, 0x56, 0xB7, 0xE9, 0xF1, 0x1B, 0xCB, 0x40, 0xC9, 0x7C, 0xC5, 0xE6, 0xF5, 0xC3, 0x0A, 0x69, 0x5E, 0x9C, 0x39, 0x11, 0x5F, 0xA2, 0xC0, 0xDB, 0x32, 0x8A, 0x3A, 0x63, 0xD8, 0x3F, 0x1A, 0xCE, 0xC6, 0x6C, 0xB3, 0x08, 0x59, 0x64, 0x14, 0x4D, 0x05, 0xD5, 0x34, 0x19, 0x2B, 0x4E, 0x3B, 0x99, 0x1F, 0xD2, 0x28, 0xAF, 0xEF, 0xE0, 0x95, 0x2D, 0xE3, 0xAB, 0x5D, 0x71, 0x53, 0x3E, 0x04, 0x47, 0x25, 0xD7, 0xF8, 0xAC, 0x8C, 0xB2, 0x9A, 0xA9, 0x9F, 0xF7, 0x88, 0xDA, 0x27, 0x9D, 0x89, 0x43, 0x0B, 0x24, 0xBD, 0x26, 0x38, 0x6A, 0xA5, 0x1C, 0xD0, 0xEE, 0x62, 0x67, 0x23, 0x9B, 0xEA, 0xDE, 0x72, 0x6D, 0x80, 0x1E, 0x3D, 0x0F, 0x2E, 0x54, 0xFF, 0x3C, 0x1D, 0xF0, 0x03, 0x5A, 0x65, 0xBC, 0x30, 0x61, 0x57, 0x6B, 0xBF, 0xA6, 0x58, 0x76, 0x2F, 0x01, 0xA1, 0x20, 0xD3, 0x74, 0x2A, 0x97, 0x8F, 0x87, 0x50, 0xAE, 0xDF, 0x55, 0xF3, 0x7F, 0xB0, 0xD6, 0x41, 0xE4, 0x4B, 0x02, 0x86, 0x16, 0x85, 0x7D, 0xBA, 0x0C, 0xD4, 0xFE, 0x7A, 0xC4, 0x51, 0x8D, 0x78, 0xCD, 0x33, 0xE1, 0x98, 0xAD, 0x79, 0x68, 0xB6, 0x17, 0xFD, 0xC8, 0x82, 0x6F, 0x4F, 0xD1, 0x8B, 0xE5, 0x66, 0xFA, 0x91, 0xB5, 0x42, 0x5C, 0x49, 0xB9, 0x73, 0xF6, 0x5B, 0x36, 0xB8, 0xB4, 0xB1, 0xEC, 0x90, 0x81, 0x92, 0xF2, 0xF4, 0x94, 0x83, 0x96, 0x9E, 0x48, 0xBE, 0xDC, 0xED, 0xCF, 0xA4, 0x70, 0x12, 0xA7, 0xA6, 0xF8, 0xF0, 0xD9, 0x1B, 0x85, 0xF4, 0xA9, 0x36, 0xA2, 0xE6, 0xCB, 0xCF, 0x9C, 0x2E, 0x78, 0xCE, 0x67, 0x07, 0x50, 0xF2, 0x0B, 0x2B, 0xB8, 0xA4, 0x1E, 0x28, 0xD7, 0x17, 0x5F, 0x74, 0xC8, 0xDA, 0x2C, 0x86, 0xAD, 0xBB, 0xD8, 0xFB, 0x6C, 0x1A, 0x8F, 0x0C, 0xE4, 0x97, 0x13, 0x2D, 0xB2, 0x5B, 0x65, 0x49, 0x45, 0x7C, 0x7B, 0x38, 0xDE, 0xAC, 0x58, 0x2F, 0x33, 0xD2, 0x52, 0x14, 0x02, 0x9D, 0xF5, 0x6A, 0x43, 0x87, 0xE0, 0x18, 0x69, 0x5E, 0x68, 0xE9, 0xAE, 0xF9, 0x63, 0xBC, 0xBF, 0xC2, 0x94, 0xB4, 0x30, 0xE8, 0x23, 0x0F, 0x64, 0x26, 0x80, 0xB3, 0x8D, 0xC1, 0xE3, 0x15, 0x34, 0x05, 0xC9, 0x29, 0xE2, 0xA8, 0x55, 0xD0, 0x37, 0xDC, 0xF6, 0xBA, 0x0D, 0x8B, 0x8E, 0x60, 0xEA, 0x84, 0x90, 0x48, 0x79, 0x10, 0x9F, 0x1F, 0x8A, 0xBD, 0xFD, 0x39, 0x04, 0x3F, 0xB9, 0x4C, 0x75, 0x3B, 0x22, 0x46, 0x7F, 0xDB, 0x2A, 0x0E, 0x35, 0x40, 0xED, 0xFC, 0x47, 0xB1, 0x7D, 0xD4, 0x62, 0x9E, 0x5D, 0xC5, 0x51, 0xA1, 0x88, 0x89, 0x11, 0x31, 0xC4, 0xFE, 0x27, 0x99, 0x5A, 0x3A, 0x91, 0x81, 0x95, 0x70, 0x1D, 0x12, 0x98, 0x4F, 0x20, 0x92, 0x56, 0x6D, 0xD5, 0xE5, 0xEC, 0xAA, 0xC0, 0xA3, 0x9A, 0x06, 0x32, 0xEE, 0x3D, 0x53, 0x08, 0xD3, 0x3E, 0xDF, 0xE1, 0xA0, 0xC6, 0xB7, 0x03, 0x6B, 0x59, 0xA5, 0x6F, 0x09, 0xD1, 0x93, 0x54, 0xF3, 0x77, 0xC7, 0xBE, 0x8C, 0xE7, 0x25, 0x76, 0x41, 0x71, 0x72, 0xCC, 0x9B, 0x16, 0x7E, 0x4B, 0x44, 0xAF, 0xF7, 0xCD, 0xAB, 0xB0, 0x7A, 0x57, 0xB5, 0x66, 0xEF, 0xEB, 0xFF, 0xB6, 0x00, 0x4E, 0xCA, 0x61, 0xC3, 0xF1, 0x4D, 0x21, 0x1C, 0xDD, 0x0A, 0xD6, 0x4A, 0x5C, 0x42, 0x83, 0x6E, 0x96, 0x19, 0x01, 0x73, 0x3C, 0xFA, 0x24, 0x82, 0x5D, 0x33, 0x3A, 0x97, 0x9D, 0xCE, 0x65, 0x39, 0xFB, 0xEB, 0x51, 0xC1, 0x59, 0x1C, 0xAF, 0x09, 0x27, 0x57, 0xA0, 0xD4, 0x75, 0xCF, 0xF9, 0x8A, 0x3C, 0xAA, 0x6E, 0x6C, 0xE8, 0xDF, 0x12, 0x2A, 0x1D, 0x02, 0xB4, 0x8C, 0x0C, 0xF7, 0x4A, 0xBD, 0xF4, 0x71, 0x16, 0xC2, 0x13, 0x86, 0x50, 0x2D, 0xA7, 0x28, 0x4B, 0x03, 0x17, 0x00, 0x15, 0x25, 0x7C, 0x19, 0xFE, 0x23, 0xF2, 0x0E, 0xC3, 0x9A, 0x0A, 0x1E, 0xF8, 0x7E, 0x70, 0x0B, 0x9E, 0x2C, 0xF3, 0xC9, 0xE4, 0xAE, 0x2E, 0x89, 0x4E, 0xA8, 0x87, 0xD9, 0x7A, 0x18, 0xDB, 0x04, 0xF0, 0xBB, 0x83, 0x8D, 0xE0, 0x92, 0x5F, 0x2B, 0x3E, 0xC0, 0xD5, 0xB6, 0x38, 0x76, 0xC5, 0x4C, 0x29, 0x36, 0x53, 0x41, 0x4D, 0x1F, 0x11, 0x4F, 0xBC, 0xD0, 0xDC, 0x96, 0x24, 0xEC, 0x9F, 0x47, 0x22, 0x6B, 0xCA, 0x56, 0x42, 0xEF, 0x99, 0x7D, 0x43, 0x63, 0x0F, 0xB8, 0x48, 0xAC, 0x55, 0xE1, 0x5E, 0xED, 0xC6, 0xD3, 0xD6, 0x40, 0x3D, 0xA5, 0x44, 0x30, 0xFC, 0xD2, 0x69, 0x32, 0xF6, 0x64, 0x01, 0x46, 0x34, 0xD1, 0xA9, 0x6D, 0x5A, 0x80, 0x35, 0xBA, 0x9C, 0x79, 0xCB, 0x61, 0x78, 0x08, 0x3F, 0x14, 0x8F, 0x94, 0xE3, 0x2F, 0xC8, 0x77, 0x54, 0x49, 0xA2, 0xFF, 0xE2, 0x6A, 0xB0, 0xD7, 0xDD, 0x5B, 0x68, 0xB2, 0x81, 0xA4, 0x1B, 0x05, 0xAB, 0x88, 0xFD, 0x20, 0xB7, 0x93, 0x7B, 0x37, 0xB1, 0x9B, 0xF5, 0xB9, 0xAD, 0xB5, 0x45, 0x73, 0xC4, 0xBE, 0x67, 0x8E, 0x1A, 0x07, 0xE6, 0x58, 0x3B, 0xEA, 0xA3, 0xC7, 0x85, 0x6F, 0x74, 0x8B, 0x60, 0x7F, 0xCD, 0x62, 0xE7, 0xE5, 0xA1, 0x10, 0xF1, 0xDE, 0x21, 0x72, 0x5C, 0x91, 0x31, 0x95, 0xDA, 0x90, 0x26, 0x52, 0xA6, 0xE9, 0x0D, 0xFA, 0x84, 0x98, 0x82, 0xB3, 0x06, 0xD8, 0xEE, 0x66, 0xCC, 0xBF, 0x35, 0x99, 0xD2, 0xA3, 0xC4, 0x83, 0x50, 0xC5, 0x7C, 0x54, 0xB0, 0x27, 0x68, 0xF7, 0xBD, 0xCA, 0x79, 0x08, 0x94, 0x85, 0x6B, 0xC2, 0xC8, 0xEF, 0x46, 0xF8, 0xC6, 0xA1, 0x29, 0x57, 0xD5, 0x5B, 0x11, 0x6F, 0x0F, 0xB6, 0xF9, 0x87, 0xAC, 0xD3, 0x1E, 0x84, 0xFD, 0x43, 0x09, 0xA2, 0x28, 0x56, 0xA0, 0xAD, 0x81, 0x55, 0x98, 0x97, 0x78, 0xE9, 0xDF, 0x1F, 0x2E, 0xE7, 0x9D, 0x59, 0x01, 0x1C, 0x52, 0x88, 0x62, 0x5D, 0x31, 0x30, 0x6D, 0x38, 0x2C, 0x24, 0x32, 0x26, 0x6E, 0xF1, 0x4C, 0x7D, 0x1D, 0x74, 0x7F, 0xC9, 0xD1, 0xD6, 0xB8, 0x51, 0xF5, 0x8D, 0x9A, 0x8F, 0xB5, 0xB3, 0xB2, 0x47, 0x3C, 0x1A, 0x8A, 0xDD, 0xF3, 0xDA, 0x5A, 0xC0, 0xD4, 0x07, 0x12, 0x53, 0x45, 0x93, 0xAB, 0xCB, 0x67, 0x48, 0x00, 0x8C, 0xE1, 0x40, 0x2F, 0x6C, 0x17, 0x22, 0xBA, 0xF4, 0xE5, 0xD7, 0x3E, 0x7E, 0x5E, 0xF6, 0x37, 0x39, 0x20, 0xA4, 0x4A, 0xCC, 0x0A, 0x03, 0x10, 0x33, 0x36, 0x9F, 0x2A, 0x70, 0x5C, 0x9C, 0xFE, 0x0D, 0x41, 0xDE, 0x49, 0x3D, 0x92, 0x89, 0xDB, 0x05, 0x6A, 0x23, 0xE0, 0x8E, 0x8B, 0xAA, 0x77, 0x69, 0x63, 0x0C, 0x2D, 0xA7, 0x14, 0x3F, 0xEB, 0xF0, 0xCD, 0x3B, 0x4B, 0xAE, 0x2B, 0xFA, 0xFB, 0x86, 0x58, 0x9B, 0x34, 0x7A, 0x95, 0xC3, 0x16, 0x96, 0xE3, 0x1B, 0xB7, 0x02, 0x44, 0x4F, 0xAF, 0xBF, 0xFC, 0xB1, 0x13, 0xEE, 0x72, 0x06, 0xD0, 0x04, 0x0B, 0xA8, 0x80, 0xBC, 0x5F, 0x65, 0xDC, 0xE2, 0x60, 0x7B, 0xBB, 0xBE, 0x4D, 0x61, 0xCE, 0xB4, 0x82, 0x18, 0xD9, 0xC7, 0x76, 0x73, 0x66, 0xC1, 0xA5, 0xFF, 0xCF, 0xEA, 0x75, 0xE8, 0x9E, 0x3A, 0xA9, 0xE6, 0x4E, 0x71, 0x21, 0x15, 0x25, 0xF2, 0xE4, 0xB9, 0xA6, 0x19, 0x42, 0x90, 0x0E, 0xEC, 0xED, 0x91, 0x64, 0xD8 }; + public static readonly byte[] BH3ExpansionKey = new byte[] { 0x87, 0xA5, 0x7F, 0xFA, 0x75, 0x53, 0x8B, 0x29, 0xA9, 0x72, 0x62, 0x68, 0xAD, 0x4D, 0x83, 0x81, 0x0A, 0xB1, 0x2E, 0xAA, 0x63, 0x88, 0xF2, 0x18, 0x6C, 0xB2, 0xBC, 0xDC, 0x4A, 0x95, 0x30, 0x07, 0x81, 0x1D, 0xEF, 0x5E, 0x16, 0xC3, 0x9B, 0x86, 0x77, 0x8F, 0xEC, 0x0E, 0x2A, 0x22, 0xF1, 0x6B, 0x52, 0x79, 0xD6, 0xEB, 0xF0, 0xC8, 0xD8, 0x0C, 0x72, 0x92, 0xDD, 0x57, 0xE1, 0xF8, 0x42, 0x2B, 0x5E, 0x44, 0x44, 0x48, 0x9A, 0xC6, 0x21, 0x6E, 0xED, 0x44, 0xE8, 0x35, 0x11, 0x5C, 0x93, 0x73, 0xA5, 0x9C, 0xA1, 0x67, 0x29, 0x51, 0x62, 0xEE, 0xE7, 0x15, 0x85, 0xBE, 0xAD, 0x20, 0x28, 0xAB, 0x17, 0xEE, 0xE4, 0x90, 0x3A, 0x7A, 0xCE, 0x28, 0xAC, 0xBF, 0xAB, 0xD0, 0xAB, 0xA2, 0xCE, 0x22, 0x47, 0x97, 0x8B, 0xA2, 0xE9, 0x47, 0x0C, 0x38, 0x3C, 0xBB, 0xBA, 0x51, 0xBE, 0x4F, 0xAD, 0xDE, 0x3A, 0xC5, 0x02, 0xDD, 0xB3, 0x50, 0x8B, 0xBA, 0xC6, 0x3E, 0xC2, 0xFD, 0xA7, 0xB8, 0x90, 0xC1, 0x82, 0x6F, 0x82, 0xBF, 0xCC, 0x4D, 0xA3, 0xF0, 0xCB, 0xAC, 0x49, 0x42, 0x8B, 0xFC, 0xFC, 0x8B, 0xDD, 0x3D, 0xA4, 0x11, 0x2F, 0x18, 0x17, 0xB2, 0x62, 0x2B, 0x5A, 0xB6, 0x64, 0xF7, 0xB3, 0xC9 }; + public static readonly byte[] BH3InitVector = new byte[] { 0x28, 0x20, 0x24, 0xC9, 0x95, 0x36, 0x70, 0x22, 0xFF, 0x23, 0x0A, 0x03, 0x3F, 0x5D, 0xD0, 0x88 }; + #endregion + + #region Mr0k + public static readonly byte[] Mr0kBlockKey = new byte[] { 0xA1, 0x55, 0x38, 0x57, 0xD0, 0xFA, 0x09, 0xEC, 0xB6, 0x74, 0x76, 0xC7, 0x60, 0x0A, 0xF1, 0x6C, 0x4C, 0x45, 0xDC, 0x03, 0x80, 0x18, 0x94, 0xDB, 0x75, 0x2E, 0x35, 0xBF, 0x74, 0x29, 0xAE, 0x2D, 0xFA, 0x37, 0x1A, 0x83, 0x05, 0xAB, 0x2A, 0x47, 0xB8, 0x4D, 0x88, 0xBF, 0xD3, 0x31, 0x96, 0x53, 0xCB, 0xA9, 0x81, 0xD4, 0xAF, 0x3D, 0xE3, 0xBA, 0xC7, 0x84, 0x23, 0xD2, 0xEC, 0xB2, 0xD7, 0x02, 0x4F, 0xC2, 0x45, 0xF4, 0x53, 0x56, 0x6E, 0xD6, 0xA6, 0xE8, 0x8C, 0x1D, 0xAE, 0x22, 0x0B, 0x75, 0xE6, 0xE7, 0x82, 0x88, 0x06, 0x61, 0xB8, 0x4B, 0xA3, 0xCE, 0x52, 0x02, 0x5C, 0x20, 0xE0, 0x19, 0x03, 0x08, 0xD2, 0x4B, 0x84, 0xF4, 0x11, 0x41, 0xC9, 0xF7, 0xE0, 0x0D, 0x86, 0x09, 0x45, 0xF0, 0xF2, 0x31, 0xE2, 0x88, 0xC6, 0xE3, 0x3E, 0x40, 0x17, 0x3A, 0xC0, 0x0C, 0x81, 0x8A, 0x80, 0xC3, 0x76, 0xA4, 0x85, 0x2D, 0x55, 0xB9, 0x6D, 0x32, 0x31, 0xA3, 0xBB, 0xEC, 0xB4, 0x50, 0xA5, 0x7E, 0xA4, 0x87, 0xEA, 0x5B, 0x9A, 0x67, 0x6C, 0xE0, 0x53, 0x4D, 0x58, 0x29, 0x84, 0x99, 0x83, 0xB0, 0x04, 0x0A, 0x43, 0x9C, 0xF6, 0xB8, 0x57, 0x5C, 0x68, 0x34, 0x60, 0x36, 0xE6, 0x73, 0x8C, 0xA8, 0x00, 0xA7, 0x64, 0x91, 0xBE, 0xBE, 0x6F, 0x1E, 0x7B, 0x57, 0x41, 0xB8, 0xAF, 0x13, 0x29, 0x87, 0x27, 0xE1, 0x64, 0xB5, 0x46, 0xA6, 0xFA, 0x9E, 0x71, 0x15, 0x85, 0xB5, 0x0D, 0x00, 0x0D, 0xA9, 0x41, 0xFE, 0x1F, 0x05, 0xD8, 0xF2, 0xFA, 0x74, 0x9F, 0x3D, 0xE8, 0x61, 0xA5, 0x06, 0x0A, 0x8A, 0xC4, 0xF6, 0x64, 0x4F, 0xCE, 0x25, 0x72, 0x81, 0x34, 0xFA, 0x81, 0x0C, 0xC9, 0xC6, 0xF4, 0xA1, 0x28, 0x4F, 0x14, 0xD3, 0x0E, 0xE1, 0xDB, 0x86, 0xE1, 0x1E, 0x3A, 0xA9, 0xB3, 0xF1, 0x17, 0xDE, 0x6E, 0x9D, 0x5B, 0x08, 0x79, 0xE0, 0x93, 0x02, 0xF0, 0xAD, 0x2B, 0x21, 0x68, 0x7A, 0xC7, 0xFE, 0xEB, 0x1E, 0xD9, 0x8B, 0x2C, 0x85, 0xCE, 0x69, 0xDB, 0xDE, 0x6D, 0x30, 0x4B, 0x0E, 0x74, 0x9C, 0xC8, 0x2D, 0x8A, 0xE5, 0x0C, 0x10, 0x6B, 0xF1, 0x11, 0x41, 0x14, 0x69, 0xF9, 0x5F, 0x68, 0xB8, 0x6A, 0xD9, 0x0E, 0x03, 0x72, 0x9C, 0x5F, 0x35, 0x2E, 0xB0, 0x88, 0x66, 0x17, 0xB3, 0xE6, 0xCB, 0xF2, 0xF2, 0xC3, 0xE4, 0x80, 0x4F, 0x6D, 0x07, 0x15, 0x85, 0x31, 0x85, 0x78, 0xC2, 0x60, 0x2E, 0xB5, 0x7A, 0x16, 0xEE, 0x61, 0xEB, 0x9B, 0x33, 0x71, 0xBD, 0x19, 0x4A, 0xBA, 0xA9, 0x72, 0xA1, 0xEC, 0x32, 0xFF, 0x27, 0x79, 0x6F, 0x33, 0x2B, 0xC7, 0xC9, 0x88, 0x7B, 0x99, 0x6F, 0x34, 0xA2, 0xD1, 0x25, 0xC6, 0x8D, 0x91, 0xE7, 0xBA, 0x7E, 0xDD, 0x16, 0x7A, 0x3D, 0x39, 0xC3, 0x07, 0x3A, 0xD5, 0xE7, 0x0D, 0x48, 0xEB, 0x28, 0x46, 0xE0, 0xE8, 0x6E, 0x8F, 0xDF, 0xA4, 0x67, 0x82, 0x8E, 0x4E, 0x95, 0xE1, 0xA3, 0x27, 0x1F, 0x54, 0x47, 0x9D, 0x97, 0xA6, 0x21, 0x00, 0x2B, 0x84, 0xBF, 0xB8, 0x3D, 0x39, 0x74, 0x72, 0x22, 0x9B, 0xC2, 0xDB, 0xEE, 0x3A, 0x9C, 0x9B, 0xB2, 0x79, 0x3D, 0xBE, 0xAC, 0xAA, 0x63, 0x81, 0xC5, 0xC6, 0x22, 0x32, 0x70, 0x51, 0xC5, 0x30, 0xE6, 0x3A, 0x6B, 0xF0, 0xCF, 0x35, 0x3D, 0xA0, 0x24, 0xA7, 0xC4, 0x15, 0xA1, 0x78, 0x3B, 0xB1, 0xE0, 0xFE, 0x0C, 0xF5, 0x9B, 0xBD, 0xA1, 0x5B, 0x5F, 0xE8, 0xAF, 0x76, 0xB7, 0x11, 0x75, 0x12, 0xEF, 0x0A, 0xBF, 0xE9, 0xBF, 0xE2, 0x73, 0xED, 0x4A, 0xE5, 0x23, 0x82, 0xA4, 0xD0, 0x1C, 0x59, 0xCF, 0x8B, 0x24, 0xAB, 0xD8, 0x43, 0xFF, 0x30, 0x70, 0xFA, 0xB8, 0x38, 0x24, 0x5A, 0x50, 0x54, 0x13, 0xEB, 0x68, 0xDD, 0x98, 0xCC, 0xCB, 0x36, 0x65, 0x1A, 0x26, 0x8C, 0xB7, 0x7B, 0x3D, 0x5A, 0x75, 0xE2, 0xD3, 0x7F, 0x42, 0x91, 0xC1, 0xBD, 0x72, 0xFF, 0x7E, 0x18, 0xCC, 0x0D, 0x39, 0xE9, 0x2D, 0x7F, 0x46, 0x90, 0xF1, 0xBD, 0x0B, 0x09, 0x5D, 0xD0, 0x0D, 0xEF, 0xAD, 0x93, 0x52, 0xEB, 0x9A, 0x4B, 0x8D, 0x20, 0x27, 0xD8, 0xE1, 0xE6, 0x30, 0xFD, 0xE2, 0x08, 0xF3, 0x91, 0x61, 0x53, 0x55, 0xC8, 0x14, 0xAB, 0x19, 0x19, 0x4F, 0xF4, 0x05, 0xEA, 0xFE, 0x76, 0x48, 0xBA, 0xD2, 0xE6, 0x8B, 0x7A, 0xA2, 0x63, 0xE1, 0x3A, 0x10, 0xE4, 0x48, 0xEB, 0xA9, 0x3C, 0x61, 0x1E, 0x0C, 0x3D, 0x0E, 0x89, 0x2E, 0xCB, 0x83, 0xEC, 0x15, 0x8E, 0x9B, 0x4D, 0x9F, 0xB9, 0x22, 0xA2, 0x63, 0xAA, 0x59, 0x9F, 0x3E, 0x96, 0xEB, 0x4B, 0x4F, 0x71, 0x56, 0x15, 0xF2, 0xED, 0x5E, 0x7E, 0x10, 0x64, 0x66, 0x3C, 0xB8, 0x90, 0x7A, 0x76, 0x6E, 0x2F, 0x6B, 0x43, 0xAB, 0x49, 0x37, 0xBF, 0x42, 0x93, 0x4C, 0x61, 0x63, 0xF9, 0x92, 0x48, 0x2D, 0xEF, 0x73, 0x86, 0xCC, 0xAC, 0x44, 0x56, 0xC5, 0x53, 0x32, 0x17, 0x7E, 0x6F, 0x03, 0x0A, 0x6A, 0x7A, 0x68, 0x32, 0x83, 0xE8, 0xDD, 0x64, 0x96, 0x2C, 0x58, 0xB0, 0x12, 0xAC, 0x92, 0xCD, 0xFA, 0x86, 0x26, 0x69, 0xE3, 0xDF, 0xD8, 0xE9, 0x5A, 0x5C, 0xEF, 0x0E, 0xBE, 0x77, 0x22, 0xB5, 0xFE, 0xCA, 0x48, 0x67, 0x44, 0xD8, 0xBE, 0x44, 0xF2, 0x92, 0x9C, 0x60, 0x40, 0xFD, 0xE6, 0xC7, 0x80, 0x09, 0x6A, 0xCD, 0x16, 0x2E, 0xF7, 0x4B, 0x6A, 0x72, 0xE1, 0x96, 0x9B, 0xE4, 0x4E, 0x99, 0xD8, 0x7E, 0x37, 0x30, 0x6F, 0xB4, 0x07, 0x63, 0x1A, 0x2F, 0x9F, 0x29, 0xB6, 0x96, 0x08, 0x3A, 0x4C, 0x88, 0x97, 0x8B, 0x83, 0x9A, 0x0F, 0xF7, 0x0B, 0xCD, 0xF5, 0x69, 0x17, 0x69, 0x23, 0xC0, 0x50, 0x56, 0xC7, 0xA7, 0x66, 0x85, 0x68, 0x37, 0x32, 0xAE, 0x3A, 0x70, 0xB9, 0x80, 0xEF, 0x3C, 0x28, 0xF9, 0xFF, 0xC4, 0x17, 0xDA, 0x61, 0xB2, 0x35, 0x5D, 0xBE, 0x87, 0x7C, 0x0B, 0x9F, 0x9E, 0x8A, 0x26, 0x88, 0xA0, 0xB9, 0x2B, 0x90, 0x5E, 0x69, 0x50, 0xFE, 0x16, 0x78, 0x96, 0x12, 0xD8, 0xFE, 0x2B, 0xEA, 0xA1, 0xB3, 0x89, 0x20, 0x1F, 0xB2, 0x59, 0x3A, 0x6A, 0x25, 0x2E, 0xA5, 0xA7, 0x6B, 0x93, 0x5C, 0xC7, 0x91, 0x89, 0xCF, 0x99, 0xEC, 0x5A, 0xAF, 0xCB, 0x8D, 0xC6, 0x79, 0x75, 0x79, 0x32, 0x8A, 0xE0, 0x9A, 0x04, 0xCB, 0xB0, 0x57, 0xB8, 0x75, 0x81, 0xFB, 0x65, 0x1B, 0xFC, 0xB2, 0xA0, 0x9B, 0xCE, 0xD7, 0x5D, 0x1D, 0x06, 0xDB, 0x6C, 0x46, 0x55, 0x7C, 0xBC, 0x45, 0x15, 0x2D, 0xBF, 0xC8, 0x0D, 0xB7, 0x02, 0x33, 0x54, 0x16, 0x14, 0xE4, 0xE3, 0xE1, 0xDF, 0x86, 0x80, 0x7F, 0x4C, 0xE8, 0x8D, 0xA3, 0x97, 0x99, 0xBB, 0x2E, 0x7A, 0x69, 0x60, 0x12, 0x58, 0x71, 0xF4, 0x50, 0xD1, 0xB2, 0xB0, 0x2E, 0x63, 0x29, 0x3A, 0x63, 0x57, 0x09, 0x99, 0x1A, 0x98, 0x39, 0x54, 0x65, 0x94, 0x06, 0xD3, 0xC3, 0x31, 0x99, 0x04, 0xD8, 0xAB, 0x5A, 0x3F, 0xA4, 0xBB, 0xE2, 0x6E, 0x79, 0x70, 0x4D, 0x7A, 0x87, 0x1D, 0x70, 0x55, 0xB0, 0xA6, 0x65, 0x20, 0x44, 0x54, 0x8D, 0x14, 0x33, 0x78, 0x4D, 0x24, 0x0A, 0x67, 0xBB, 0xE9, 0x3E, 0xE7, 0xCA, 0x5E, 0x98, 0x26, 0x49, 0x11, 0x9F, 0xE0, 0x0B, 0xAB, 0x03, 0xD0, 0x0C, 0xD3, 0x38, 0xCA, 0xA0, 0xEF, 0xD9, 0x59, 0xAA, 0x1F, 0xA0, 0x72, 0x8C, 0xC9, 0xBA, 0x99, 0x9D, 0x6F, 0x6B, 0x42, 0x79, 0x3A, 0x9F, 0x3B, 0xBB, 0x9D, 0x22, 0x88, 0xD5, 0x01, 0x93, 0x2F, 0xC4, 0x23, 0x16, 0xD0, 0xA6, 0x35, 0xA3 }; + public static readonly byte[] Mr0kExpansionKey = new byte[] { 0x2F, 0xE0, 0x89, 0x14, 0xE8, 0x23, 0x4E, 0xE6, 0x91, 0x6D, 0xED, 0xED, 0x86, 0x62, 0x85, 0x1C, 0xD7, 0x0F, 0x87, 0x2B, 0x64, 0xF3, 0xE0, 0x40, 0xDC, 0x27, 0x17, 0x4C, 0xC2, 0x73, 0x4E, 0x6D, 0x00, 0xE7, 0x91, 0x04, 0x4E, 0x14, 0x60, 0x8D, 0x1A, 0xE8, 0x36, 0x4F, 0xCF, 0xFB, 0x50, 0xA7, 0x5D, 0x89, 0x51, 0x7B, 0xBB, 0xEB, 0x4F, 0x1E, 0x56, 0xA0, 0xB0, 0x1F, 0x48, 0x67, 0x86, 0x21, 0x31, 0xF8, 0xA2, 0xB5, 0xED, 0x90, 0xA4, 0x46, 0xF1, 0x4E, 0x36, 0x38, 0x63, 0x03, 0xA9, 0x8C, 0x05, 0xD3, 0x2B, 0x17, 0xB2, 0x18, 0x93, 0x34, 0xE0, 0xAA, 0x63, 0x2E, 0x39, 0x99, 0x7D, 0x08, 0x33, 0x0C, 0x3F, 0xB0, 0x07, 0xEE, 0xD2, 0xB6, 0x8E, 0x0A, 0xB4, 0x3D, 0xA6, 0xBF, 0x77, 0xAF, 0xBE, 0x17, 0x83, 0xC0, 0x83, 0x2A, 0x57, 0x83, 0xB2, 0xA8, 0xF7, 0xA3, 0xDE, 0xE6, 0x58, 0x4C, 0xA5, 0x33, 0xF1, 0xE0, 0x9B, 0x3D, 0x7B, 0xC7, 0x26, 0x0B, 0x0E, 0x87, 0xAA, 0x10, 0xB8, 0x5B, 0xCD, 0x9D, 0x01, 0x0B, 0x64, 0x92, 0xA8, 0xE4, 0xDE, 0x76, 0xA8, 0xE3, 0xAD, 0xA2, 0xC6, 0xB9, 0x79, 0xBC, 0xEC, 0xF7, 0x37, 0xCF, 0x6C, 0x3D, 0x0D, 0x68, 0xB1, 0x1E, 0xFC, 0x38, 0x43, 0x85 }; + public static readonly byte[] Mr0kInitVector = new byte[] { 0xA1, 0xF2, 0x7E, 0xB3, 0x5E, 0xDC, 0x88, 0xC7, 0xB6, 0x6C, 0xD8, 0x76, 0xD6, 0x7B, 0xB2, 0x69 }; + #endregion + + #region Mark + public static readonly byte[] MarkKey = new byte[] { 0x71, 0x98, 0xAA, 0xE6, 0xCE, 0x1B, 0x05, 0x4A, 0xE9, 0xFF, 0x45, 0x21, 0xC3, 0x38, 0x5E, 0x3C, 0x0F, 0xFB, 0xF5, 0xBB, 0xF6, 0x81, 0x48, 0x15, 0xFA, 0xD7, 0x77, 0x35, 0x82, 0x17, 0xD9, 0x9D, 0x56, 0x28, 0x2E, 0xA9, 0x51, 0xBA, 0x66, 0x2F, 0x22, 0xDD, 0xBB, 0x8A, 0x3B, 0xAD, 0x90, 0x63, 0xC6, 0x64, 0xFB, 0xD6, 0xCF, 0xA8, 0xBC, 0x48, 0x02, 0xC3, 0xBE, 0x36, 0xB2, 0x93, 0xBC, 0xD9 }; + #endregion + + #region TOT + public static readonly byte[] ToTKey = { 0x25, 0x7D, 0x02, 0x00, 0x41, 0xC8, 0x03, 0x00, 0x73, 0xA7, 0x05, 0x00, 0xBF, 0x44, 0x07, 0x00, 0xDD, 0x90, 0x08, 0x00, 0xDF, 0x69, 0x0A, 0x00 }; + #endregion + + #region EnsembleStar + public static readonly byte[] EnsembleStarKey1 = new byte[] { 0x6D, 0xD4, 0x01, 0x09, 0x4E, 0x1B, 0xBB, 0x09, 0x01, 0x5C, 0x4F, 0x5D, 0x13, 0x65, 0x31, 0xDE, 0x6F, 0x0B, 0x16, 0x21, 0x2C, 0x59, 0x80, 0x95, 0x96, 0xAC, 0x79, 0x7F, 0x13 }; + public static readonly byte[] EnsembleStarKey2 = new byte[] { 0x0E, 0x6A, 0x7C, 0x76, 0xBB, 0xD5, 0x68, 0x24, 0xC9, 0xEE, 0xFD, 0x50, 0xF0, 0x07, 0xA7, 0x06, 0x55, 0xB1, 0x85, 0x28, 0x1D, 0xA2, 0xD7, 0x91, 0xA1, 0xF6, 0x70, 0x97, 0x08, 0x58, 0x75, 0x0E }; + public static readonly byte[] EnsembleStarKey3 = new byte[] { 0xF7, 0x8A, 0x4C, 0xF1, 0xB4, 0x4F, 0x61, 0x4A, 0x16, 0x2C, 0x35, 0x4A, 0xAE, 0xB8, 0x23, 0x85 }; + #endregion + } +} diff --git a/AssetStudio/Game/Crypto/MT19937_64.cs b/AssetStudio/Crypto/MT19937_64.cs similarity index 76% rename from AssetStudio/Game/Crypto/MT19937_64.cs rename to AssetStudio/Crypto/MT19937_64.cs index 64158d4..efa7a1e 100644 --- a/AssetStudio/Game/Crypto/MT19937_64.cs +++ b/AssetStudio/Crypto/MT19937_64.cs @@ -1,32 +1,28 @@ namespace AssetStudio { - public class MT19937_64 + public static class MT19937_64 { private const ulong N = 312; private const ulong M = 156; private const ulong MATRIX_A = 0xB5026F5AA96619E9L; private const ulong UPPER_MASK = 0xFFFFFFFF80000000; private const ulong LOWER_MASK = 0X7FFFFFFFUL; - private static ulong[] mt = new ulong[N + 1]; + + private static readonly ulong[] mt = new ulong[N + 1]; private static ulong mti = N + 1; - public MT19937_64(ulong seed) - { - this.Seed(seed); - } - - public void Seed(ulong seed) + public static void Init(ulong seed) { mt[0] = seed; for (mti = 1; mti < N; mti++) { - mt[mti] = (6364136223846793005L * (mt[mti - 1] ^ (mt[mti - 1] >> 62)) + mti); + mt[mti] = 6364136223846793005L * (mt[mti - 1] ^ (mt[mti - 1] >> 62)) + mti; } } - public ulong Int63() + public static ulong Int64() { - ulong x = 0; + ulong x; ulong[] mag01 = new ulong[2] { 0x0UL, MATRIX_A }; if (mti >= N) @@ -34,7 +30,7 @@ ulong kk; if (mti == N + 1) { - Seed(5489UL); + Init(5489UL); } for (kk = 0; kk < (N - M); kk++) { @@ -60,9 +56,14 @@ return x; } - public ulong IntN(ulong value) + public static long Int63() { - return Int63() % value; + return (long)(Int64() >> 1); + } + + public static ulong IntN(ulong value) + { + return (ulong)Int63() % value; } } } \ No newline at end of file diff --git a/AssetStudio/Crypto/Mr0kUtils.cs b/AssetStudio/Crypto/Mr0kUtils.cs new file mode 100644 index 0000000..e213085 --- /dev/null +++ b/AssetStudio/Crypto/Mr0kUtils.cs @@ -0,0 +1,72 @@ +using System; +using System.Buffers; +using System.Buffers.Binary; + +namespace AssetStudio +{ + public static class Mr0kUtils + { + private const int BlockSize = 0x400; + + private static readonly byte[] mr0kMagic = { 0x6D, 0x72, 0x30, 0x6B }; + public static Span Decrypt(Span data, Mr0k mr0k) + { + var key1 = new byte[0x10]; + var key2 = new byte[0x10]; + var key3 = new byte[0x10]; + + data.Slice(4, 0x10).CopyTo(key1); + data.Slice(0x74, 0x10).CopyTo(key2); + data.Slice(0x84, 0x10).CopyTo(key3); + + var encryptedBlockSize = Math.Min(0x10 * ((data.Length - 0x94) >> 7), BlockSize); + + if (!mr0k.InitVector.IsNullOrEmpty()) + { + for (int i = 0; i < mr0k.InitVector.Length; i++) + key2[i] ^= mr0k.InitVector[i]; + } + + if (!mr0k.SBox.IsNullOrEmpty()) + { + for (int i = 0; i < 0x10; i++) + key1[i] = mr0k.SBox[(i % 4 * 0x100) | key1[i]]; + } + + AES.Decrypt(key1, mr0k.ExpansionKey); + AES.Decrypt(key3, mr0k.ExpansionKey); + + for (int i = 0; i < key1.Length; i++) + { + key1[i] ^= key3[i]; + } + + key1.CopyTo(data.Slice(0x84, 0x10)); + + var seed1 = BinaryPrimitives.ReadUInt64LittleEndian(key2); + var seed2 = BinaryPrimitives.ReadUInt64LittleEndian(key3); + var seed = seed2 ^ seed1 ^ (seed1 + (uint)data.Length - 20); + + var encryptedBlock = data.Slice(0x94, encryptedBlockSize); + var seedSpan = BitConverter.GetBytes(seed); + for (var i = 0; i < encryptedBlockSize; i++) + { + encryptedBlock[i] ^= (byte)(seedSpan[i % seedSpan.Length] ^ mr0k.BlockKey[i % mr0k.BlockKey.Length]); + } + + data = data[0x14..]; + + if (!mr0k.PostKey.IsNullOrEmpty()) + { + for (int i = 0; i < 0xC00; i++) + { + data[i] ^= mr0k.PostKey[i % mr0k.PostKey.Length]; + } + } + + return data; + } + + public static bool IsMr0k(ReadOnlySpan data) => data[..4].SequenceEqual(mr0kMagic); + } +} diff --git a/AssetStudio/Game/Crypto/XORShift128.cs b/AssetStudio/Crypto/XORShift128.cs similarity index 54% rename from AssetStudio/Game/Crypto/XORShift128.cs rename to AssetStudio/Crypto/XORShift128.cs index 9b2fca6..fecc481 100644 --- a/AssetStudio/Game/Crypto/XORShift128.cs +++ b/AssetStudio/Crypto/XORShift128.cs @@ -3,40 +3,42 @@ using System.Buffers.Binary; namespace AssetStudio { - public class XORShift128 + public static class XORShift128 { - public uint x = 0, y = 0, z = 0, w = 0, initseed = 0; + public static bool Init = false; + public static uint x = 0, y = 0, z = 0, w = 0, initseed = 0; const long SEED = 0x61C8864E7A143579; const uint MT19937 = 0x6C078965; - public void InitSeed(int seed) + public static void InitSeed(uint seed) { - initseed = (uint)seed; - x = (uint)seed; + initseed = seed; + x = seed; y = MT19937 * x + 1; z = MT19937 * y + 1; w = MT19937 * z + 1; + Init = true; } - public uint XORShift() + public static uint XORShift() { uint t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ t ^ (t >> 8); } - public uint NextUInt32() + public static uint NextUInt32() { return XORShift(); } - public int NextDecryptInt() => BinaryPrimitives.ReadInt32LittleEndian(NextDecrypt(4)); - public uint NextDecryptUInt() => BinaryPrimitives.ReadUInt32LittleEndian(NextDecrypt(4)); + public static int NextDecryptInt() => BinaryPrimitives.ReadInt32LittleEndian(NextDecrypt(4)); + public static uint NextDecryptUInt() => BinaryPrimitives.ReadUInt32LittleEndian(NextDecrypt(4)); - public long NextDecryptLong() => BinaryPrimitives.ReadInt64LittleEndian(NextDecrypt(8)); + public static long NextDecryptLong() => BinaryPrimitives.ReadInt64LittleEndian(NextDecrypt(8)); - public byte[] NextDecrypt(int size) + public static byte[] NextDecrypt(int size) { var valueBytes = new byte[size]; var key = size * initseed - SEED; diff --git a/AssetStudio/CryptoStream.cs b/AssetStudio/CryptoStream.cs new file mode 100644 index 0000000..88ee4df --- /dev/null +++ b/AssetStudio/CryptoStream.cs @@ -0,0 +1,27 @@ +using System.IO; + +namespace AssetStudio +{ + public class CryptoStream : BlockStream + { + private const long _dataPosition = 0x2A; + + private readonly byte[] _xorpad; + + public CryptoStream(Stream stream, byte[] xorpad) : base(stream, _dataPosition) + { + _xorpad = xorpad; + } + + public override int Read(byte[] buffer, int offset, int count) + { + var pos = RelativePosition; + var read = base.Read(buffer, offset, count); + for (int i = 0; i < count; i++) + { + buffer[i] ^= _xorpad[pos++ % _xorpad.Length]; + } + return read; + } + } +} diff --git a/AssetStudio/EndianBinaryReader.cs b/AssetStudio/EndianBinaryReader.cs index 8a9c417..a6cd87d 100644 --- a/AssetStudio/EndianBinaryReader.cs +++ b/AssetStudio/EndianBinaryReader.cs @@ -1,6 +1,8 @@ using System; using System.Buffers.Binary; +using System.Collections.Generic; using System.IO; +using System.Text; namespace AssetStudio { @@ -10,11 +12,10 @@ namespace AssetStudio public EndianType Endian; - public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian, Game game = null) : base(stream) + public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian, bool leaveOpen = false) : base(stream, Encoding.UTF8, leaveOpen) { Endian = endian; buffer = new byte[8]; - Game = game; } public long Position @@ -23,8 +24,8 @@ namespace AssetStudio set => BaseStream.Position = value; } - public long[] BundlePos = Array.Empty(); - public Game Game; + public long Length => BaseStream.Length; + public long Remaining => Length - Position; public override short ReadInt16() { @@ -108,9 +109,179 @@ namespace AssetStudio return base.ReadDouble(); } - public Float ReadFloat() + public void AlignStream() { - return new Float(ReadSingle()); + AlignStream(4); + } + + public void AlignStream(int alignment) + { + var pos = Position; + var mod = pos % alignment; + if (mod != 0) + { + Position += alignment - mod; + } + } + + public string ReadAlignedString() + { + var length = ReadInt32(); + if (length > 0 && length <= Remaining) + { + var stringData = ReadBytes(length); + var result = Encoding.UTF8.GetString(stringData); + AlignStream(4); + return result; + } + return ""; + } + + public string ReadStringToNull(int maxLength = 32767) + { + var bytes = new List(); + int count = 0; + while (Remaining > 0 && count < maxLength) + { + var b = ReadByte(); + if (b == 0) + { + break; + } + bytes.Add(b); + count++; + } + return Encoding.UTF8.GetString(bytes.ToArray()); + } + + public Quaternion ReadQuaternion() + { + return new Quaternion(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); + } + + public Vector2 ReadVector2() + { + return new Vector2(ReadSingle(), ReadSingle()); + } + + public Vector3 ReadVector3() + { + return new Vector3(ReadSingle(), ReadSingle(), ReadSingle()); + } + + public Vector4 ReadVector4() + { + return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); + } + + public Color ReadColor4() + { + return new Color(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); + } + + public Matrix4x4 ReadMatrix() + { + return new Matrix4x4(ReadSingleArray(16)); + } + + public int ReadMhy0Int() + { + var buffer = ReadBytes(6); + return buffer[2] | (buffer[4] << 8) | (buffer[0] << 0x10) | (buffer[5] << 0x18); + } + + public uint ReadMhy0UInt() + { + var buffer = ReadBytes(7); + return (uint)(buffer[1] | (buffer[6] << 8) | (buffer[3] << 0x10) | (buffer[2] << 0x18)); + } + + public string ReadMhy0String() + { + var pos = BaseStream.Position; + var str = ReadStringToNull(); + BaseStream.Position += 0x105 - (BaseStream.Position - pos); + return str; + } + + private T[] ReadArray(Func del, int length) + { + var array = new T[length]; + for (int i = 0; i < length; i++) + { + array[i] = del(); + } + return array; + } + + public bool[] ReadBooleanArray() + { + return ReadArray(ReadBoolean, ReadInt32()); + } + + public byte[] ReadUInt8Array() + { + return ReadBytes(ReadInt32()); + } + + public ushort[] ReadUInt16Array() + { + return ReadArray(ReadUInt16, ReadInt32()); + } + + public int[] ReadInt32Array() + { + return ReadArray(ReadInt32, ReadInt32()); + } + + public int[] ReadInt32Array(int length) + { + return ReadArray(ReadInt32, length); + } + + public uint[] ReadUInt32Array() + { + return ReadArray(ReadUInt32, ReadInt32()); + } + + public uint[][] ReadUInt32ArrayArray() + { + return ReadArray(ReadUInt32Array, ReadInt32()); + } + + public uint[] ReadUInt32Array(int length) + { + return ReadArray(ReadUInt32, length); + } + + public float[] ReadSingleArray() + { + return ReadArray(ReadSingle, ReadInt32()); + } + + public float[] ReadSingleArray(int length) + { + return ReadArray(ReadSingle, length); + } + + public string[] ReadStringArray() + { + return ReadArray(ReadAlignedString, ReadInt32()); + } + + public Vector2[] ReadVector2Array() + { + return ReadArray(ReadVector2, ReadInt32()); + } + + public Vector4[] ReadVector4Array() + { + return ReadArray(ReadVector4, ReadInt32()); + } + + public Matrix4x4[] ReadMatrixArray() + { + return ReadArray(ReadMatrix, ReadInt32()); } } } diff --git a/AssetStudio/ExportTypeList.cs b/AssetStudio/ExportTypeList.cs new file mode 100644 index 0000000..e0edee0 --- /dev/null +++ b/AssetStudio/ExportTypeList.cs @@ -0,0 +1,18 @@ +namespace AssetStudio +{ + public enum ExportListType + { + XML, + JSON + } + + public static class ExportListTypeExtensions + { + public static string GetExtension(this ExportListType type) => type switch + { + ExportListType.XML => ".xml", + ExportListType.JSON => ".json", + _ => throw new System.NotImplementedException(), + }; + } +} diff --git a/AssetStudio/Extensions/BinaryReaderExtensions.cs b/AssetStudio/Extensions/BinaryReaderExtensions.cs deleted file mode 100644 index cf66c7c..0000000 --- a/AssetStudio/Extensions/BinaryReaderExtensions.cs +++ /dev/null @@ -1,192 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Linq; - -namespace AssetStudio -{ - public static class BinaryReaderExtensions - { - public static void AlignStream(this BinaryReader reader) - { - reader.AlignStream(4); - } - - public static void AlignStream(this BinaryReader reader, int alignment) - { - var pos = reader.BaseStream.Position; - var mod = pos % alignment; - if (mod != 0) - { - reader.BaseStream.Position += alignment - mod; - } - } - - public static string ReadAlignedString(this BinaryReader reader) - { - var length = reader.ReadInt32(); - if (length > 0 && length <= reader.BaseStream.Length - reader.BaseStream.Position) - { - var stringData = reader.ReadBytes(length); - var result = Encoding.UTF8.GetString(stringData); - reader.AlignStream(4); - return result; - } - return ""; - } - - public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767) - { - var bytes = new List(); - int count = 0; - while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength) - { - var b = reader.ReadByte(); - if (b == 0) - { - break; - } - bytes.Add(b); - count++; - } - return Encoding.UTF8.GetString(bytes.ToArray()); - } - - public static Quaternion ReadQuaternion(this BinaryReader reader) - { - return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - } - - public static Vector2 ReadVector2(this BinaryReader reader) - { - return new Vector2(reader.ReadSingle(), reader.ReadSingle()); - } - - public static Vector3 ReadVector3(this BinaryReader reader) - { - return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - } - - public static Vector4 ReadVector4(this BinaryReader reader) - { - return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - } - - public static Color ReadColor4(this BinaryReader reader) - { - return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - } - - public static Matrix4x4 ReadMatrix(this BinaryReader reader) - { - return new Matrix4x4(reader.ReadSingleArray(16)); - } - - public static int ReadMhy0Int1(this BinaryReader reader) - { - var buffer = reader.ReadBytes(7); - return buffer[1] | (buffer[6] << 8) | (buffer[3] << 0x10) | (buffer[2] << 0x18); - } - - public static int ReadMhy0Int2(this BinaryReader reader) - { - var buffer = reader.ReadBytes(6); - return buffer[2] | (buffer[4] << 8) | (buffer[0] << 0x10) | (buffer[5] << 0x18); - } - - public static string ReadMhy0String(this BinaryReader reader) - { - var bytes = reader.ReadBytes(0x100); - return Encoding.UTF8.GetString(bytes.TakeWhile(b => !b.Equals(0)).ToArray()); - } - - public static bool ReadMhy0Bool(this BinaryReader reader) - { - var value = reader.ReadMhy0Int2(); - var bytes = BitConverter.GetBytes(value); - Array.Reverse(bytes); - return BitConverter.ToBoolean(bytes, 0); - } - - private static T[] ReadArray(Func del, int length) - { - var array = new T[length]; - for (int i = 0; i < length; i++) - { - array[i] = del(); - } - return array; - } - - public static bool[] ReadBooleanArray(this BinaryReader reader) - { - return ReadArray(reader.ReadBoolean, reader.ReadInt32()); - } - - public static byte[] ReadUInt8Array(this BinaryReader reader) - { - return reader.ReadBytes(reader.ReadInt32()); - } - - public static ushort[] ReadUInt16Array(this BinaryReader reader) - { - return ReadArray(reader.ReadUInt16, reader.ReadInt32()); - } - - public static int[] ReadInt32Array(this BinaryReader reader) - { - return ReadArray(reader.ReadInt32, reader.ReadInt32()); - } - - public static int[] ReadInt32Array(this BinaryReader reader, int length) - { - return ReadArray(reader.ReadInt32, length); - } - - public static uint[] ReadUInt32Array(this BinaryReader reader) - { - return ReadArray(reader.ReadUInt32, reader.ReadInt32()); - } - - public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader) - { - return ReadArray(reader.ReadUInt32Array, reader.ReadInt32()); - } - - public static uint[] ReadUInt32Array(this BinaryReader reader, int length) - { - return ReadArray(reader.ReadUInt32, length); - } - - public static float[] ReadSingleArray(this BinaryReader reader) - { - return ReadArray(reader.ReadSingle, reader.ReadInt32()); - } - - public static float[] ReadSingleArray(this BinaryReader reader, int length) - { - return ReadArray(reader.ReadSingle, length); - } - - public static string[] ReadStringArray(this BinaryReader reader) - { - return ReadArray(reader.ReadAlignedString, reader.ReadInt32()); - } - - public static Vector2[] ReadVector2Array(this BinaryReader reader) - { - return ReadArray(reader.ReadVector2, reader.ReadInt32()); - } - - public static Vector4[] ReadVector4Array(this BinaryReader reader) - { - return ReadArray(reader.ReadVector4, reader.ReadInt32()); - } - - public static Matrix4x4[] ReadMatrixArray(this BinaryReader reader) - { - return ReadArray(reader.ReadMatrix, reader.ReadInt32()); - } - } -} diff --git a/AssetStudio/Extensions/BinaryWriterExtensions.cs b/AssetStudio/Extensions/BinaryWriterExtensions.cs deleted file mode 100644 index fcaac82..0000000 --- a/AssetStudio/Extensions/BinaryWriterExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.IO; -using System.Text; - -namespace AssetStudio -{ - public static class BinaryWriterExtensions - { - public static void AlignStream(this BinaryWriter writer, int alignment) - { - var pos = writer.BaseStream.Position; - var mod = pos % alignment; - if (mod != 0) - { - writer.Write(new byte[alignment - mod]); - } - } - - public static void WriteAlignedString(this BinaryWriter writer, string str) - { - var bytes = Encoding.UTF8.GetBytes(str); - writer.Write(bytes.Length); - writer.Write(bytes); - writer.AlignStream(4); - } - } -} diff --git a/AssetStudio/Extensions/BitConverterExtensions.cs b/AssetStudio/Extensions/BitConverterExtensions.cs deleted file mode 100644 index ac57b66..0000000 --- a/AssetStudio/Extensions/BitConverterExtensions.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace AssetStudio -{ - public static class BitConverterExtensions - { - [StructLayout(LayoutKind.Explicit)] - private struct FloatUIntUnion - { - [FieldOffset(0)] - public uint Int; - [FieldOffset(0)] - public float Float; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint ToUInt32(float value) - { - return new FloatUIntUnion { Float = value }.Int; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong ToUInt64(double value) - { - return unchecked((ulong)BitConverter.DoubleToInt64Bits(value)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ToSingle(uint value) - { - return new FloatUIntUnion { Int = value }.Float; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ToDouble(ulong value) - { - return BitConverter.Int64BitsToDouble(unchecked((long)value)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(ushort value, byte[] buffer, int offset) - { - buffer[offset + 0] = unchecked((byte)(value >> 0)); - buffer[offset + 1] = unchecked((byte)(value >> 8)); - } - - public static void GetBytes(uint value, byte[] buffer, int offset) - { - buffer[offset + 0] = unchecked((byte)(value >> 0)); - buffer[offset + 1] = unchecked((byte)(value >> 8)); - buffer[offset + 2] = unchecked((byte)(value >> 16)); - buffer[offset + 3] = unchecked((byte)(value >> 24)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static short Swap(short value) - { - return unchecked((short)(Swap(unchecked((ushort)value)))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ushort Swap(ushort value) - { - return unchecked((ushort)(value >> 8 | value << 8)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Swap(int value) - { - return unchecked((int)(Swap(unchecked((uint)value)))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint Swap(uint value) - { - value = value >> 16 | value << 16; - return ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Swap(long value) - { - return unchecked((long)(Swap(unchecked((ulong)value)))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong Swap(ulong value) - { - value = value >> 32 | value << 32; - value = ((value & 0xFFFF0000FFFF0000) >> 16) | ((value & 0x0000FFFF0000FFFF) << 16); - return ((value & 0xFF00FF00FF00FF00) >> 8) | ((value & 0x00FF00FF00FF00FF) << 8); - } - - public static int GetDigitsCount(uint value) - { - int count = 0; - while (value != 0) - { - value /= 10; - count++; - } - return count; - } - } -} diff --git a/AssetStudio/Extensions/ByteArrayExtensions.cs b/AssetStudio/Extensions/ByteArrayExtensions.cs new file mode 100644 index 0000000..e035aae --- /dev/null +++ b/AssetStudio/Extensions/ByteArrayExtensions.cs @@ -0,0 +1,38 @@ +using System.Text; + +namespace AssetStudio +{ + public static class ByteArrayExtensions + { + public static bool IsNullOrEmpty(this T[] array) => array == null || array.Length == 0; + public static byte[] ToUInt4Array(this byte[] source) => ToUInt4Array(source, 0, source.Length); + public static byte[] ToUInt4Array(this byte[] source, int offset, int size) + { + var buffer = new byte[size * 2]; + for (var i = 0; i < size; i++) + { + var idx = i * 2; + buffer[idx] = (byte)(source[offset + i] >> 4); + buffer[idx + 1] = (byte)(source[offset + i] & 0xF); + } + return buffer; + } + public static int Search(this byte[] src, string value, int offset = 0) => Search(src, Encoding.UTF8.GetBytes(value), offset); + public static int Search(this byte[] src, byte[] pattern, int offset) + { + int maxFirstCharSlot = src.Length - pattern.Length + 1; + for (int i = offset; i < maxFirstCharSlot; i++) + { + if (src[i] != pattern[0]) + continue; + + for (int j = pattern.Length - 1; j >= 1; j--) + { + if (src[i + j] != pattern[j]) break; + if (j == 1) return i; + } + } + return -1; + } + } +} diff --git a/AssetStudio/Extensions/PrimitiveExtensions.cs b/AssetStudio/Extensions/PrimitiveExtensions.cs deleted file mode 100644 index af49cbb..0000000 --- a/AssetStudio/Extensions/PrimitiveExtensions.cs +++ /dev/null @@ -1,79 +0,0 @@ -namespace AssetStudio -{ - public static class PrimitiveExtensions - { - public static int ParseDigit(this char _this) - { - return _this - '0'; - } - - public static string ToHexString(this byte _this) - { - return _this.ToString("x2"); - } - - public static string ToHexString(this short _this) - { - ushort value = unchecked((ushort)_this); - return ToHexString(value); - } - - public static string ToHexString(this ushort _this) - { - ushort reverse = unchecked((ushort)(((0xFF00 & _this) >> 8) | ((0x00FF & _this) << 8))); - return reverse.ToString("x4"); - } - - public static string ToHexString(this int _this) - { - uint value = unchecked((uint)_this); - return ToHexString(value); - } - - public static string ToHexString(this uint _this) - { - uint reverse = ((0xFF000000 & _this) >> 24) | ((0x00FF0000 & _this) >> 8) | ((0x0000FF00 & _this) << 8) | ((0x000000FF & _this) << 24); - return reverse.ToString("x8"); - } - - public static string ToHexString(this long _this) - { - ulong value = unchecked((ulong)_this); - return ToHexString(value); - } - - public static string ToHexString(this ulong _this) - { - ulong reverse = (_this & 0x00000000000000FFUL) << 56 | (_this & 0x000000000000FF00UL) << 40 | - (_this & 0x0000000000FF0000UL) << 24 | (_this & 0x00000000FF000000UL) << 8 | - (_this & 0x000000FF00000000UL) >> 8 | (_this & 0x0000FF0000000000UL) >> 24 | - (_this & 0x00FF000000000000UL) >> 40 | (_this & 0xFF00000000000000UL) >> 56; - return reverse.ToString("x16"); - } - - public static string ToHexString(this float _this) - { - uint value = BitConverterExtensions.ToUInt32(_this); - return ToHexString(value); - } - - public static string ToHexString(this double _this) - { - ulong value = BitConverterExtensions.ToUInt64(_this); - return ToHexString(value); - } - - public static int ToClosestInt(this long _this) - { - if (_this > int.MaxValue) - { - return int.MaxValue; - } - if (_this < int.MinValue) - { - return int.MinValue; - } - return unchecked((int)_this); - } - } -} diff --git a/AssetStudio/Extensions/StringBuilderExtensions.cs b/AssetStudio/Extensions/StringBuilderExtensions.cs deleted file mode 100644 index 04b0057..0000000 --- a/AssetStudio/Extensions/StringBuilderExtensions.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System.Text; - -namespace AssetStudio -{ - public static class StringBuilderExtensions - { - static StringBuilderExtensions() - { - for (int i = 0; i <= byte.MaxValue; i++) - { - ByteHexRepresentations[i] = i.ToString("x2"); - } - } - - public static StringBuilder AppendHex(this StringBuilder _this, byte value) - { - _this.Append(ByteHexRepresentations[value]); - return _this; - } - - public static StringBuilder AppendHex(this StringBuilder _this, ushort value) - { - _this.Append(ByteHexRepresentations[(value >> 0) & 0xFF]); - _this.Append(ByteHexRepresentations[(value >> 8) & 0xFF]); - return _this; - } - - public static StringBuilder AppendHex(this StringBuilder _this, short value) - { - return AppendHex(_this, unchecked((ushort)value)); - } - - public static StringBuilder AppendHex(this StringBuilder _this, uint value) - { - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 0) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 8) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 16) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 24) & 0xFF)]); - return _this; - } - - public static StringBuilder AppendHex(this StringBuilder _this, int value) - { - return AppendHex(_this, unchecked((uint)value)); - } - - public static StringBuilder AppendHex(this StringBuilder _this, ulong value) - { - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 0) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 8) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 16) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 24) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 32) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 40) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 48) & 0xFF)]); - _this.Append(ByteHexRepresentations[unchecked((int)(value >> 56) & 0xFF)]); - return _this; - } - - public static StringBuilder AppendHex(this StringBuilder _this, long value) - { - return AppendHex(_this, unchecked((ulong)value)); - } - - public static StringBuilder AppendHex(this StringBuilder _this, float value) - { - return AppendHex(_this, BitConverterExtensions.ToUInt32(value)); - } - - public static StringBuilder AppendHex(this StringBuilder _this, double value) - { - return AppendHex(_this, BitConverterExtensions.ToUInt64(value)); - } - - public static StringBuilder AppendIndent(this StringBuilder _this, int count) - { - for (int i = 0; i < count; i++) - { - _this.Append('\t'); - } - return _this; - } - - public static readonly string HexAlphabet = "0123456789abcdef"; - public static readonly string[] ByteHexRepresentations = new string[256]; - } -} diff --git a/AssetStudio/FileReader.cs b/AssetStudio/FileReader.cs index 19ab9da..ceda873 100644 --- a/AssetStudio/FileReader.cs +++ b/AssetStudio/FileReader.cs @@ -1,5 +1,6 @@ using System.IO; using System.Linq; +using static AssetStudio.ImportHelper; namespace AssetStudio { @@ -8,40 +9,32 @@ namespace AssetStudio public string FullPath; public string FileName; public FileType FileType; - public long Length; private static readonly byte[] gzipMagic = { 0x1f, 0x8b }; private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 }; private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 }; private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 }; + private static readonly byte[] mhy0Magic = { 0x6D, 0x68, 0x79, 0x30 }; + private static readonly byte[] narakaMagic = { 0x15, 0x1E, 0x1C, 0x0D, 0x0D, 0x23, 0x21 }; + private static readonly byte[] gunfireMagic = { 0x7C, 0x6D, 0x79, 0x72, 0x27, 0x7A, 0x73, 0x78, 0x3F }; - public FileReader(string path, Game game = null) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), game) { } - public FileReader(string path, Stream stream, Game game = null) : base(stream, EndianType.BigEndian, game) + public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } + + public FileReader(string path, Stream stream, bool leaveOpen = false) : base(stream, EndianType.BigEndian, leaveOpen) { - Game = game; FullPath = Path.GetFullPath(path); FileName = Path.GetFileName(path); FileType = CheckFileType(); - Length = stream.Length; - } private FileType CheckFileType() { - if (IsSerializedFile()) - { - return FileType.AssetsFile; - } - else if (Game != null) - { - return FileType.GameFile; - } - var signature = this.ReadStringToNull(20); Position = 0; switch (signature) { + case "ENCR": case "UnityWeb": case "UnityRaw": case "UnityArchive": @@ -49,6 +42,8 @@ namespace AssetStudio return FileType.BundleFile; case "UnityWebData1.0": return FileType.WebFile; + case "blk": + return FileType.BlkFile; default: { byte[] magic = ReadBytes(2); @@ -71,7 +66,26 @@ namespace AssetStudio magic = ReadBytes(4); Position = 0; if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic)) + { return FileType.ZipFile; + } + if (mhy0Magic.SequenceEqual(magic)) + { + return FileType.Mhy0File; + } + magic = ReadBytes(7); + Position = 0; + if (narakaMagic.SequenceEqual(magic)) + { + return FileType.BundleFile; + } + magic = ReadBytes(9); + Position = 0; + if (gunfireMagic.SequenceEqual(magic)) + { + Position = 0x32; + return FileType.BundleFile; + } return FileType.ResourceFile; } } @@ -113,4 +127,35 @@ namespace AssetStudio return true; } } + + public static class FileReaderExtensions + { + public static FileReader PreProcessing(this FileReader reader, Game game) + { + if (reader.FileType == FileType.ResourceFile || !game.Type.IsNormal()) + { + switch (game.Type) + { + case GameType.GI_Pack: + reader = DecryptPack(reader, game); + break; + case GameType.GI_CB1: + reader = DecryptMark(reader); + break; + case GameType.EnsembleStars: + reader = DecryptEnsembleStar(reader); + break; + case GameType.OPFP: + reader = ParseOPFP(reader); + break; + } + } + if (reader.FileType == FileType.BundleFile && game.Type.IsBlockFile()) + { + reader.FileType = FileType.BlockFile; + } + + return reader; + } + } } diff --git a/AssetStudio/FileType.cs b/AssetStudio/FileType.cs index 7ea63d5..b6258e3 100644 --- a/AssetStudio/FileType.cs +++ b/AssetStudio/FileType.cs @@ -10,11 +10,13 @@ namespace AssetStudio { AssetsFile, BundleFile, - GameFile, WebFile, ResourceFile, GZipFile, BrotliFile, - ZipFile + ZipFile, + BlkFile, + Mhy0File, + BlockFile } } diff --git a/AssetStudio/Game/BH3/WMVFile.cs b/AssetStudio/Game/BH3/WMVFile.cs deleted file mode 100644 index d693df3..0000000 --- a/AssetStudio/Game/BH3/WMVFile.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; - -namespace AssetStudio -{ - public class WMVFile - { - public Dictionary Bundles = new Dictionary(); - public WMVFile(FileReader reader) - { - if (reader.BundlePos.Length != 0) - { - foreach (var pos in reader.BundlePos) - { - reader.Position = pos; - var bundle = new BundleFile(reader); - Bundles.Add(pos, bundle.FileList); - } - } - else - { - while (reader.Position != reader.Length) - { - var pos = reader.Position; - var bundle = new BundleFile(reader); - Bundles.Add(pos, bundle.FileList); - } - } - } - } -} diff --git a/AssetStudio/Game/CB1/CB1File.cs b/AssetStudio/Game/CB1/CB1File.cs deleted file mode 100644 index a85a0e6..0000000 --- a/AssetStudio/Game/CB1/CB1File.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace AssetStudio -{ - public class CB1File - { - public Dictionary Bundles = new Dictionary(); - public CB1File(FileReader reader) - { - var data = Mark.Decrypt(reader); - - using (var ms = new MemoryStream(data)) - using (var subReader = new FileReader(reader.FullPath, ms, reader.Game)) - { - var bundle = new BundleFile(subReader); - Bundles.Add(0, bundle.FileList); - } - } - } -} diff --git a/AssetStudio/Game/CBX/CBXFile.cs b/AssetStudio/Game/CBX/CBXFile.cs deleted file mode 100644 index 69313d2..0000000 --- a/AssetStudio/Game/CBX/CBXFile.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace AssetStudio -{ - public class CBXFile - { - public Dictionary Bundles = new Dictionary(); - public CBXFile(FileReader reader) - { - var data = Blk.Decrypt(reader); - - using (var ms = new MemoryStream(data)) - using (var subReader = new FileReader(reader.FullPath, ms, reader.Game)) - { - if (subReader.BundlePos.Length != 0) - { - foreach (var pos in subReader.BundlePos) - { - subReader.Position = pos; - var bundle = new BundleFile(subReader); - Bundles.Add(pos, bundle.FileList); - } - } - else - { - while (subReader.Position != subReader.BaseStream.Length) - { - var pos = subReader.Position; - var bundle = new BundleFile(subReader); - if (bundle.FileList == null) - continue; - Bundles.Add(pos, bundle.FileList); - } - } - } - } - } -} diff --git a/AssetStudio/Game/Crypto/Blk.cs b/AssetStudio/Game/Crypto/Blk.cs deleted file mode 100644 index 135582d..0000000 --- a/AssetStudio/Game/Crypto/Blk.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; - -namespace AssetStudio -{ - public static class Blk - { - private const int KeySize = 0x1000; - private const int SeedBlockSize = 0x800; - - public static byte[] ExpansionKey; - public static byte[] SBox; - public static byte[] ConstKey; - public static ulong ConstVal; - - public static byte[] Decrypt(FileReader reader) - { - reader.Endian = EndianType.LittleEndian; - - var signature = reader.ReadStringToNull(); - if (signature != "blk") - throw new Exception("not a blk"); - - var count = reader.ReadInt32(); - var key = reader.ReadBytes(count); - reader.Position += count; - var seedSize = Math.Min(reader.ReadInt16(), SBox == null ? SeedBlockSize : SeedBlockSize * 2); - - var dataSize = (int)(reader.BaseStream.Length - reader.BaseStream.Position); - var buffer = reader.ReadBytes(dataSize); - - long keySeed = -1; - for (int i = 0; i < seedSize / 8; i++) - { - keySeed ^= BitConverter.ToInt64(buffer, i * 8); - } - - DecryptKey(key); - - var keyLow = BitConverter.ToUInt64(key, 0); - var keyHigh = BitConverter.ToUInt64(key, 8); - var seed = keyLow ^ keyHigh ^ (ulong)keySeed ^ ConstVal; - - var xorpad = new byte[KeySize]; - var rand = new MT19937_64(seed); - for (int i = 0; i < KeySize / 8; i++) - { - Buffer.BlockCopy(BitConverter.GetBytes(rand.Int63()), 0, xorpad, i * 8, 8); - } - - for (int i = 0; i < dataSize; i++) - { - buffer[i] ^= xorpad[i % KeySize]; - } - - return buffer; - } - - private static void DecryptKey(byte[] key) - { - if (SBox != null) - { - for (int i = 0; i < 0x10; i++) - { - key[i] = SBox[(i % 4 * 0x100) | key[i]]; - } - } - - AES.Decrypt(key, ExpansionKey); - - for (int i = 0; i < 0x10; i++) - { - key[i] ^= ConstKey[i]; - } - } - } -} diff --git a/AssetStudio/Game/Crypto/Crypto.cs b/AssetStudio/Game/Crypto/Crypto.cs deleted file mode 100644 index ba3c2b1..0000000 --- a/AssetStudio/Game/Crypto/Crypto.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; - -namespace AssetStudio -{ - public static class Crypto - { - private static readonly byte[] GF256Exp = new byte[] { 0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35, 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA, 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31, 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD, 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88, 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A, 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3, 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0, 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41, 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75, 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80, 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54, 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA, 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E, 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17, 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01 }; - private static readonly byte[] GF256Log = new byte[] { 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1A, 0xC6, 0x4B, 0xC7, 0x1B, 0x68, 0x33, 0xEE, 0xDF, 0x03, 0x64, 0x04, 0xE0, 0x0E, 0x34, 0x8D, 0x81, 0xEF, 0x4C, 0x71, 0x08, 0xC8, 0xF8, 0x69, 0x1C, 0xC1, 0x7D, 0xC2, 0x1D, 0xB5, 0xF9, 0xB9, 0x27, 0x6A, 0x4D, 0xE4, 0xA6, 0x72, 0x9A, 0xC9, 0x09, 0x78, 0x65, 0x2F, 0x8A, 0x05, 0x21, 0x0F, 0xE1, 0x24, 0x12, 0xF0, 0x82, 0x45, 0x35, 0x93, 0xDA, 0x8E, 0x96, 0x8F, 0xDB, 0xBD, 0x36, 0xD0, 0xCE, 0x94, 0x13, 0x5C, 0xD2, 0xF1, 0x40, 0x46, 0x83, 0x38, 0x66, 0xDD, 0xFD, 0x30, 0xBF, 0x06, 0x8B, 0x62, 0xB3, 0x25, 0xE2, 0x98, 0x22, 0x88, 0x91, 0x10, 0x7E, 0x6E, 0x48, 0xC3, 0xA3, 0xB6, 0x1E, 0x42, 0x3A, 0x6B, 0x28, 0x54, 0xFA, 0x85, 0x3D, 0xBA, 0x2B, 0x79, 0x0A, 0x15, 0x9B, 0x9F, 0x5E, 0xCA, 0x4E, 0xD4, 0xAC, 0xE5, 0xF3, 0x73, 0xA7, 0x57, 0xAF, 0x58, 0xA8, 0x50, 0xF4, 0xEA, 0xD6, 0x74, 0x4F, 0xAE, 0xE9, 0xD5, 0xE7, 0xE6, 0xAD, 0xE8, 0x2C, 0xD7, 0x75, 0x7A, 0xEB, 0x16, 0x0B, 0xF5, 0x59, 0xCB, 0x5F, 0xB0, 0x9C, 0xA9, 0x51, 0xA0, 0x7F, 0x0C, 0xF6, 0x6F, 0x17, 0xC4, 0x49, 0xEC, 0xD8, 0x43, 0x1F, 0x2D, 0xA4, 0x76, 0x7B, 0xB7, 0xCC, 0xBB, 0x3E, 0x5A, 0xFB, 0x60, 0xB1, 0x86, 0x3B, 0x52, 0xA1, 0x6C, 0xAA, 0x55, 0x29, 0x9D, 0x97, 0xB2, 0x87, 0x90, 0x61, 0xBE, 0xDC, 0xFC, 0xBC, 0x95, 0xCF, 0xCD, 0x37, 0x3F, 0x5B, 0xD1, 0x53, 0x39, 0x84, 0x3C, 0x41, 0xA2, 0x6D, 0x47, 0x14, 0x2A, 0x9E, 0x5D, 0x56, 0xF2, 0xD3, 0xAB, 0x44, 0x11, 0x92, 0xD9, 0x23, 0x20, 0x2E, 0x89, 0xB4, 0x7C, 0xB8, 0x26, 0x77, 0x99, 0xE3, 0xA5, 0x67, 0x4A, 0xED, 0xDE, 0xC5, 0x31, 0xFE, 0x18, 0x0D, 0x63, 0x8C, 0x80, 0xC0, 0xF7, 0x70, 0x07 }; - - private static readonly byte[] Mhy0ShiftRow = new byte[] { 0x0B, 0x02, 0x08, 0x0C, 0x01, 0x05, 0x00, 0x0F, 0x06, 0x07, 0x09, 0x03, 0x0D, 0x04, 0x0E, 0x0A, 0x04, 0x05, 0x07, 0x0A, 0x02, 0x0F, 0x0B, 0x08, 0x0E, 0x0D, 0x09, 0x06, 0x0C, 0x03, 0x00, 0x01, 0x08, 0x00, 0x0C, 0x06, 0x04, 0x0B, 0x07, 0x09, 0x05, 0x03, 0x0F, 0x01, 0x0D, 0x0A, 0x02, 0x0E }; - private static readonly byte[] Mhy0Key = new byte[] { 0x48, 0x14, 0x36, 0xED, 0x8E, 0x44, 0x5B, 0xB6 }; - private static readonly byte[] Mhy0Mul = new byte[] { 0xA7, 0x99, 0x66, 0x50, 0xB9, 0x2D, 0xF0, 0x78 }; - - public static readonly byte[] GISBox = new byte[] { 0xF7, 0xE7, 0xD8, 0xB8, 0x64, 0x31, 0xD1, 0x74, 0x88, 0xAA, 0xB4, 0x8B, 0x6A, 0xA3, 0xFC, 0x55, 0x59, 0xC5, 0x6D, 0xC9, 0x9A, 0x11, 0x2F, 0x37, 0xAD, 0x35, 0x15, 0x62, 0x61, 0x04, 0x44, 0x01, 0xDD, 0x47, 0x3D, 0xFF, 0x8F, 0x51, 0xAF, 0x0F, 0x19, 0x23, 0x92, 0x13, 0x00, 0x53, 0x4B, 0x67, 0x21, 0x1C, 0x1B, 0x94, 0xE2, 0x29, 0x9F, 0x4C, 0xFB, 0xBB, 0x75, 0xF0, 0xFE, 0x1F, 0xDB, 0xEF, 0x1D, 0xF1, 0x3A, 0x1A, 0x05, 0x06, 0xCE, 0xDE, 0x63, 0x0A, 0x6B, 0x2D, 0x28, 0x41, 0x6C, 0x0C, 0x42, 0xDC, 0x58, 0xB6, 0x39, 0x2E, 0xD2, 0xF6, 0x2B, 0xAC, 0x84, 0x96, 0x17, 0xF3, 0x3F, 0x8D, 0xAB, 0x95, 0xCD, 0x30, 0x0E, 0x66, 0x90, 0xF4, 0xED, 0xE0, 0x8E, 0xC2, 0x78, 0x2C, 0x7E, 0xF8, 0x5D, 0x02, 0x91, 0xFA, 0x3C, 0xDA, 0xB7, 0x6F, 0xF9, 0x4F, 0x14, 0x5E, 0xEA, 0x24, 0x56, 0x9E, 0xC1, 0xA5, 0x85, 0xD7, 0x08, 0x83, 0x4E, 0xF5, 0x76, 0x32, 0x86, 0x5C, 0xD3, 0x09, 0x5F, 0xFD, 0x36, 0x03, 0xEE, 0xE3, 0x34, 0x77, 0x79, 0x18, 0xBD, 0xDF, 0x97, 0x71, 0xBA, 0x65, 0x68, 0x7A, 0x54, 0x80, 0x48, 0x38, 0x5B, 0x4D, 0x5A, 0x7F, 0x0B, 0x7C, 0xA6, 0x7B, 0x25, 0xD6, 0x0D, 0x40, 0xD0, 0x07, 0x99, 0x9D, 0x93, 0x69, 0xD9, 0x8C, 0xB3, 0xB5, 0xA4, 0x1E, 0xCB, 0x33, 0x82, 0xE9, 0xC3, 0x60, 0xA7, 0xAE, 0x45, 0xBE, 0xB1, 0x46, 0xB2, 0x9C, 0x22, 0xC7, 0x81, 0x98, 0xA9, 0xD5, 0x6E, 0xE1, 0x10, 0xCA, 0xBC, 0x4A, 0x70, 0xD4, 0xC4, 0x72, 0x12, 0xCF, 0x2A, 0x87, 0x16, 0xC8, 0x73, 0xA1, 0x3E, 0x52, 0x50, 0xA8, 0x57, 0x27, 0xEC, 0xCC, 0x7D, 0xE4, 0xA0, 0x89, 0xBF, 0xE5, 0x8A, 0x20, 0xEB, 0xC0, 0xA2, 0x49, 0xB9, 0xE8, 0x26, 0xC6, 0xE6, 0xB0, 0x3B, 0x9B, 0xF2, 0x43, 0x5E, 0xB0, 0xE6, 0x0D, 0xF9, 0x87, 0xD7, 0x8A, 0xDF, 0xE7, 0x19, 0x99, 0x6F, 0xD5, 0x5B, 0x4E, 0xCB, 0xC2, 0x48, 0xD2, 0xF2, 0x44, 0x35, 0x03, 0xE9, 0x86, 0xD0, 0x95, 0x02, 0x4A, 0x04, 0x62, 0xC5, 0x9D, 0x1D, 0xE2, 0xFD, 0x53, 0x08, 0x8D, 0x5D, 0x75, 0xD9, 0x3F, 0x94, 0x59, 0x14, 0x29, 0x98, 0x76, 0x8C, 0x79, 0x2E, 0x8F, 0x39, 0x0C, 0x4C, 0xC8, 0xC0, 0x81, 0x9C, 0x10, 0xBB, 0xAF, 0xF7, 0xE5, 0xB2, 0xB3, 0xEE, 0x56, 0x57, 0xB8, 0xFA, 0x40, 0x7A, 0x72, 0x77, 0x24, 0x6C, 0xC6, 0x47, 0x3A, 0x74, 0xCF, 0x89, 0xB4, 0x9B, 0x26, 0xAA, 0x38, 0x09, 0xC3, 0x1C, 0xDE, 0x9F, 0xDD, 0x16, 0x1F, 0x55, 0xBD, 0xAD, 0xAC, 0x80, 0x4F, 0x64, 0x4B, 0x71, 0xB7, 0xF6, 0x06, 0x2B, 0xC7, 0x01, 0xEA, 0x46, 0xA6, 0xEB, 0x3D, 0xCA, 0x07, 0x34, 0x1B, 0xFF, 0x7C, 0x7D, 0x2D, 0x37, 0x67, 0x60, 0x9A, 0xC4, 0x97, 0x7F, 0xD6, 0xBE, 0xAE, 0x85, 0x25, 0x88, 0x65, 0xA2, 0x00, 0xB6, 0x8E, 0xD4, 0x6E, 0x1A, 0x63, 0x36, 0x92, 0xC1, 0xE1, 0x15, 0xA5, 0x58, 0x3B, 0x7E, 0x22, 0x2F, 0x84, 0x0F, 0x5C, 0x96, 0xB1, 0xF1, 0x6D, 0x8B, 0xF4, 0xA8, 0xB5, 0x0B, 0xFE, 0x23, 0xE3, 0xCE, 0xF8, 0xF5, 0x51, 0x45, 0x43, 0x18, 0x1E, 0xD1, 0xBA, 0xBC, 0x90, 0x21, 0x70, 0x30, 0xC9, 0x2A, 0xEC, 0x61, 0x7B, 0x66, 0x5F, 0x13, 0x33, 0x20, 0x6B, 0xCD, 0x3C, 0xA0, 0x93, 0x31, 0xB9, 0x05, 0x82, 0xFB, 0x3E, 0x17, 0x12, 0x6A, 0x0A, 0xCC, 0x4D, 0xA1, 0x73, 0x52, 0x78, 0xBF, 0x28, 0x50, 0x69, 0xDC, 0x68, 0x42, 0xE0, 0xA4, 0x2C, 0xEF, 0xF0, 0x11, 0xE8, 0x91, 0x49, 0x83, 0x5A, 0xF3, 0x32, 0xDB, 0xAB, 0xDA, 0x27, 0x0E, 0xED, 0xA3, 0xFC, 0x41, 0xA7, 0xA9, 0xD3, 0x9E, 0xE4, 0xD8, 0x54, 0x95, 0xAE, 0xF0, 0xD5, 0x73, 0x24, 0xD2, 0xA5, 0x99, 0x0B, 0x1B, 0xC4, 0x9A, 0xD8, 0x69, 0x6F, 0x25, 0xED, 0x8E, 0x91, 0x63, 0xF8, 0x35, 0x62, 0x5B, 0x94, 0x88, 0xB2, 0x5C, 0x0F, 0xDD, 0xA4, 0x7A, 0x1A, 0x12, 0xC6, 0x37, 0x44, 0xF1, 0x4E, 0xB9, 0x4D, 0x43, 0xD1, 0xAD, 0xEB, 0xB4, 0x46, 0x80, 0x30, 0x5E, 0xE4, 0x87, 0x6E, 0x0A, 0x82, 0xCF, 0x74, 0x38, 0xB5, 0xC1, 0xD6, 0x01, 0x05, 0xE8, 0x83, 0xA9, 0x6D, 0xCE, 0xA8, 0xC5, 0x51, 0xA3, 0x3F, 0xDA, 0x03, 0xD0, 0x3A, 0x39, 0x6C, 0x11, 0x97, 0x68, 0x54, 0xC0, 0x4B, 0xDF, 0x19, 0x0C, 0x21, 0x1F, 0x66, 0xBD, 0xE9, 0x61, 0x49, 0xC8, 0x42, 0xBC, 0xEC, 0x7F, 0xC3, 0x4F, 0x2E, 0xA1, 0x58, 0x3D, 0x81, 0xE3, 0x14, 0xB8, 0x02, 0x23, 0x9E, 0x77, 0x2B, 0x33, 0xA6, 0x93, 0x13, 0x34, 0x0E, 0x06, 0x45, 0xFB, 0x07, 0x75, 0x0D, 0x1E, 0x40, 0xAB, 0x7D, 0xF5, 0xBB, 0x55, 0xEF, 0x04, 0x65, 0x79, 0x2F, 0xCA, 0xF3, 0x29, 0xCB, 0xEA, 0x17, 0xF4, 0xE6, 0x71, 0x4C, 0x50, 0x26, 0xD9, 0x78, 0x5F, 0x09, 0x9C, 0x1C, 0x85, 0x31, 0x22, 0x9B, 0xC9, 0xE0, 0x8F, 0xAC, 0x57, 0x8B, 0x7C, 0x47, 0x7E, 0x16, 0xF7, 0x08, 0x5A, 0x59, 0x1D, 0xC7, 0xF9, 0x00, 0x2D, 0x60, 0x3C, 0x9F, 0x96, 0xA2, 0xBA, 0x20, 0x70, 0xF6, 0x48, 0xB0, 0x2C, 0x72, 0xE1, 0x64, 0xE7, 0xFF, 0xB7, 0x56, 0xA7, 0x53, 0x84, 0xD7, 0xE2, 0xD4, 0xA0, 0xB1, 0x8C, 0xE5, 0x2A, 0xDC, 0x15, 0x28, 0x5D, 0x3B, 0x36, 0x7B, 0x86, 0x6A, 0xDB, 0x10, 0xBE, 0x6B, 0xFE, 0x9D, 0x18, 0xDE, 0x76, 0xF2, 0xCD, 0xB6, 0x32, 0xFC, 0x41, 0xAF, 0xBF, 0x67, 0xB3, 0xAA, 0xC2, 0x8A, 0xFD, 0x89, 0xCC, 0xFA, 0x90, 0x98, 0x8D, 0x52, 0xD3, 0xEE, 0x92, 0x3E, 0x4A, 0x27, 0x2A, 0xD7, 0x9E, 0x02, 0x53, 0x63, 0xEA, 0xE9, 0x8F, 0x35, 0x22, 0x7F, 0xFE, 0xCA, 0x75, 0x46, 0x57, 0x94, 0xD9, 0x4E, 0xD2, 0xD4, 0x76, 0xA1, 0xC3, 0xD8, 0xBC, 0x9B, 0x84, 0x87, 0x91, 0x51, 0xB1, 0xAB, 0x81, 0x64, 0x47, 0xAF, 0x9D, 0x6A, 0x5B, 0x2D, 0xD6, 0x95, 0x77, 0x03, 0xC1, 0x10, 0xAD, 0x61, 0x0C, 0xBF, 0x11, 0x34, 0x7E, 0x01, 0x38, 0x20, 0x4B, 0xB6, 0x4A, 0x1A, 0x45, 0x99, 0x5F, 0x26, 0xBB, 0xC5, 0xCD, 0x23, 0xF1, 0xF7, 0xB4, 0x8E, 0xE1, 0xF8, 0x68, 0x56, 0x29, 0xD5, 0x3D, 0xEF, 0x12, 0x28, 0xC4, 0x2E, 0x79, 0xA6, 0x48, 0x85, 0x73, 0x14, 0xE4, 0xC6, 0x6B, 0x92, 0x30, 0x27, 0x93, 0x13, 0x0D, 0xE2, 0xC9, 0xF0, 0x65, 0xDF, 0xFB, 0xE3, 0x06, 0x2F, 0x8C, 0x4C, 0x18, 0x15, 0xD3, 0x49, 0x3E, 0x07, 0x59, 0xB0, 0x88, 0xA9, 0xC8, 0x3B, 0x86, 0xEE, 0x5C, 0x7A, 0x5E, 0xFF, 0x8D, 0xAC, 0x08, 0xE6, 0x60, 0x54, 0xA0, 0x7D, 0x40, 0x33, 0xA8, 0xFC, 0xE0, 0x37, 0x98, 0xBD, 0xEC, 0x09, 0xB2, 0x71, 0x58, 0x1F, 0xDE, 0x74, 0x89, 0x36, 0x52, 0x66, 0xA2, 0x3C, 0x96, 0x5D, 0x50, 0x90, 0x41, 0xF5, 0x17, 0x2B, 0x0B, 0xDC, 0xF6, 0x00, 0x83, 0xDD, 0x6D, 0xB5, 0x3A, 0x9C, 0xB8, 0x70, 0x7C, 0x43, 0x69, 0xFD, 0x32, 0x1B, 0xED, 0x0F, 0x55, 0x97, 0xC2, 0xFA, 0x39, 0x4F, 0x9A, 0x82, 0x19, 0xE7, 0x78, 0x6E, 0xCB, 0xA4, 0xBE, 0x24, 0xB3, 0xF3, 0xCC, 0xCF, 0x1C, 0xF9, 0x44, 0xA5, 0x1E, 0x80, 0x3F, 0xD0, 0x21, 0xA3, 0xE8, 0x31, 0x05, 0x16, 0x8A, 0xBA, 0x67, 0x0E, 0xE5, 0xB7, 0xD1, 0x42, 0x1D, 0xDB, 0x72, 0x6C, 0xA7, 0xCE, 0x04, 0x4D, 0xDA, 0xC7, 0x8B, 0x9F, 0x6F, 0x0A, 0x2C, 0xEB, 0xF2, 0x5A, 0x7B, 0xAA, 0x25, 0xC0, 0x62, 0xAE, 0xF4, 0xB9 }; - public static readonly byte[] GIExpansionKey = new byte[] { 0x54, 0x2F, 0xED, 0x67, 0x5D, 0xDD, 0x11, 0x2E, 0xB7, 0x40, 0x13, 0xE3, 0x29, 0xAB, 0x6D, 0x28, 0x3E, 0xD0, 0x4D, 0x51, 0xD3, 0x0B, 0x8F, 0x3C, 0x8F, 0x7D, 0x56, 0x0D, 0xB3, 0x5C, 0x5B, 0xDF, 0x8F, 0x05, 0x26, 0xE5, 0x9D, 0x36, 0xEE, 0x17, 0xF9, 0x40, 0xC3, 0x05, 0x6A, 0xF1, 0x1D, 0x2C, 0x79, 0xED, 0xC6, 0xE2, 0x0C, 0x15, 0x87, 0x93, 0xC1, 0x91, 0xE5, 0x8D, 0x44, 0x10, 0x98, 0x34, 0x08, 0x7A, 0xB6, 0x76, 0xAA, 0xB5, 0x34, 0x21, 0xEE, 0x72, 0x58, 0x27, 0x3F, 0x72, 0x5A, 0x93, 0x75, 0x78, 0x60, 0xC0, 0xA2, 0xF5, 0x52, 0x97, 0x9F, 0xF5, 0x28, 0x86, 0x23, 0x3A, 0xB4, 0xEA, 0xC3, 0x40, 0x12, 0x39, 0x92, 0xE2, 0x33, 0xD8, 0x7A, 0x39, 0x44, 0xA9, 0x5B, 0x58, 0x5F, 0x7C, 0xD9, 0xFC, 0x9F, 0xEF, 0x3F, 0x3A, 0x05, 0x5B, 0xA5, 0x4D, 0x1D, 0x63, 0x33, 0xD5, 0xEB, 0x43, 0x42, 0x79, 0x71, 0x85, 0x57, 0x92, 0xF8, 0xDE, 0xED, 0x7D, 0xE3, 0xF8, 0x33, 0x20, 0x2C, 0x92, 0x22, 0xE5, 0x6E, 0xCC, 0x1D, 0x21, 0x71, 0x04, 0xB8, 0xA7, 0x8D, 0x3B, 0xE6, 0x19, 0x53, 0x36, 0x1E, 0x14, 0x40, 0x12, 0xED, 0x7B, 0x85, 0x47, 0x8D, 0xD2, 0xCD, 0xF8, 0x4D, 0x71, 0xBC, 0x62 }; - public static readonly byte[] GIConstKey = new byte[] { 0xE3, 0xFC, 0x2D, 0x26, 0x9C, 0xC5, 0xA2, 0xEC, 0xD3, 0xF8, 0xC6, 0xD3, 0x77, 0xC2, 0x49, 0xB9 }; - public static readonly ulong GIConstVal = 0x567BA22BABB08098; - - public static readonly byte[] CBXExpansionKey = new byte[] { 0x3C, 0x5E, 0xAD, 0x0F, 0xD5, 0x09, 0x27, 0x3F, 0xB8, 0x70, 0x00, 0x9A, 0xCD, 0x30, 0x1B, 0xEB, 0xB7, 0x04, 0x71, 0xD9, 0x39, 0x80, 0x21, 0x29, 0xB5, 0xCC, 0x7A, 0xB2, 0xAE, 0xB6, 0x75, 0x14, 0x63, 0x2A, 0x82, 0x34, 0x70, 0xA5, 0x40, 0xEB, 0xF9, 0x4E, 0x95, 0x1C, 0x0A, 0xA4, 0xD0, 0xF6, 0x56, 0x1E, 0x0E, 0xE3, 0x7B, 0xBF, 0x0D, 0xC5, 0xD3, 0x04, 0xF3, 0x43, 0xDA, 0x76, 0x37, 0xDD, 0xAD, 0xE9, 0xF6, 0x97, 0x54, 0xD2, 0x56, 0xA2, 0x00, 0xBE, 0x96, 0xD0, 0x61, 0x4F, 0x8A, 0xBE, 0x5C, 0x32, 0x74, 0xC8, 0xFD, 0x7F, 0x2C, 0xFC, 0x5D, 0x4E, 0xD0, 0x6B, 0x2A, 0x2B, 0xF8, 0xDE, 0x12, 0x5B, 0xA2, 0x58, 0x8C, 0x4E, 0x02, 0xE5, 0x3C, 0xA6, 0xDB, 0x02, 0xBF, 0xAA, 0xE5, 0x12, 0xE0, 0xEF, 0x09, 0x36, 0xF6, 0xA0, 0xE5, 0x60, 0xE1, 0x62, 0xE4, 0x54, 0x02, 0xA7, 0xD1, 0x71, 0xC0, 0xF6, 0xE0, 0xFF, 0xDD, 0x01, 0xBA, 0xD5, 0x26, 0x94, 0x2D, 0x85, 0xA3, 0x7D, 0xDF, 0x0F, 0x94, 0x2F, 0xD6, 0x39, 0xE6, 0xEC, 0xCA, 0x86, 0x73, 0xD5, 0x66, 0x6A, 0x98, 0x92, 0x86, 0xCE, 0x20, 0xB4, 0xF0, 0x4C, 0xAA, 0xDD, 0x5A, 0xD5, 0x78, 0x2C, 0x81, 0xBE, 0xAE, 0x3A, 0x31, 0x14 }; - public static readonly byte[] CBXConstKey = new byte[] { 0xA2, 0x25, 0x25, 0x99, 0xB7, 0x62, 0xF4, 0x39, 0x28, 0xE1, 0xB7, 0x73, 0x91, 0x05, 0x25, 0x87 }; - public static readonly ulong CBXConstVal = 0xCEAC3B5A867837AC; - - public static readonly byte[] BH3Key = new byte[] { 0x8B, 0xD8, 0xD8, 0x92, 0xB6, 0x54, 0xB5, 0xCC, 0xBA, 0x8B, 0x35, 0x0F, 0x3C, 0x86, 0x97, 0x2B, 0x6C, 0x29, 0x21, 0x23, 0xB1, 0x32, 0x86, 0x00, 0x9C, 0x59, 0xED, 0x30, 0x49, 0xEA, 0xA4, 0x34, 0x8B, 0x65, 0x79, 0x98, 0xBB, 0x91, 0xD4, 0x90, 0xA8, 0xBB, 0x14, 0xB3, 0x4B, 0xF2, 0x24, 0x0B, 0x86, 0xF5, 0x1B, 0x42, 0xBB, 0x32, 0x44, 0xD5, 0xA8, 0xD2, 0x0F, 0x33, 0x16, 0xF3, 0x80, 0x7A, 0x46, 0x1B, 0xC7, 0x8F, 0x06, 0xD2, 0xE3, 0xC0, 0x36, 0x1B, 0x6E, 0x30, 0x10, 0x98, 0xC8, 0x21, 0x08, 0x56, 0x75, 0x76, 0x9D, 0xA1, 0xE7, 0xF8, 0xF4, 0x5F, 0x6E, 0xB3, 0x71, 0xE4, 0xB9, 0x43, 0x44, 0xC1, 0x7A, 0x00, 0xF8, 0x77, 0x20, 0x2B, 0x06, 0x6B, 0xED, 0x3F, 0xE9, 0x74, 0x13, 0x6E, 0xA5, 0x61, 0x2B, 0x1E, 0x45, 0x9C, 0x74, 0xB9, 0x82, 0x22, 0x9F, 0x32, 0xBC, 0xEF, 0x9B, 0x88, 0x5A, 0x9E, 0x55, 0xCC, 0xE5, 0xB5, 0xA2, 0x6A, 0x01, 0xEF, 0xEC, 0x13, 0xCF, 0x3E, 0x4F, 0x7C, 0xA0, 0xF8, 0x91, 0xE6, 0x70, 0x6D, 0x4B, 0xDD, 0xEC, 0x24, 0x14, 0x7B, 0x97, 0x23, 0x00, 0x93, 0x0F, 0xCE, 0xB6, 0x38, 0xB5, 0xB6, 0xB0, 0x95, 0x4E, 0x0E, 0x07, 0xE0, 0xEE, 0x6D, 0x0E, 0xDC, 0xB2, 0x3D, 0xC9, 0x7A, 0xA5, 0x41, 0xB2, 0x02, 0xAD, 0xDE, 0x72, 0x10, 0x65, 0xCC, 0x7A, 0x7E, 0xCC, 0xD0, 0x69, 0xC6, 0xA7, 0xB2, 0xB6, 0x38, 0x76, 0x55, 0x6B, 0xA0, 0xAD, 0xF1, 0xEF, 0xA0, 0x9D, 0xCF, 0x2E, 0x89, 0x07, 0x64, 0x6F, 0x1D, 0xE0, 0x51, 0x43, 0xB3, 0x4C, 0x15, 0x65, 0x71, 0x76, 0xFD, 0x1E, 0x0A, 0xA3, 0x00, 0x18, 0x36, 0x12, 0xB0, 0xFB, 0x31, 0xCE, 0x22, 0x2D, 0xD4, 0xFD, 0x09, 0x1D, 0x1A, 0x99, 0x19, 0xFA, 0x02, 0x48, 0x4D, 0xC8, 0x42, 0xA1, 0x2B, 0x8D, 0xA6, 0xF2, 0x53, 0x19, 0x92, 0x57, 0x67, 0xBD, 0xB2, 0x90, 0xE6, 0x01, 0x36, 0xEE, 0x99, 0x1D, 0xC6, 0x30, 0xA0, 0x41, 0xFE, 0xAC, 0x06, 0xC0, 0x56, 0xEE, 0xF4, 0xB8, 0x31, 0xDF, 0xDE, 0xE6, 0x9E, 0x6E, 0x61, 0x42, 0x59, 0xD6, 0x99, 0x0F, 0x87, 0x1E, 0xDD, 0x9D, 0xB5, 0xCA, 0xBC, 0xF9, 0x82, 0xE2, 0x27, 0xD2, 0x2C, 0x5E, 0x51, 0xD8, 0x11, 0x17, 0x4A, 0x32, 0xA3, 0x6E, 0xCB, 0x33, 0xEE, 0x00, 0xC2, 0x22, 0xF8, 0x2C, 0x7E, 0x52, 0x0B, 0xB8, 0x84, 0x83, 0xD7, 0x65, 0x5A, 0x18, 0x4F, 0xB9, 0x54, 0x26, 0x05, 0x02, 0x4D, 0x52, 0x65, 0xAA, 0x03, 0x30, 0x16, 0x45, 0x43, 0x41, 0xDC, 0xBA, 0x75, 0xBD, 0xF2, 0x23, 0xCB, 0xF5, 0x32, 0xE6, 0x41, 0xEC, 0x06, 0x09, 0x86, 0xC2, 0x2C, 0xC0, 0xD7, 0x09, 0xE7, 0xA2, 0xE3, 0x61, 0xFC, 0x10, 0x03, 0x96, 0xF2, 0x3D, 0x31, 0x97, 0x0F, 0x0B, 0x3C, 0x64, 0x9D, 0xC8, 0x72, 0x1C, 0xF5, 0x6B, 0x9A, 0x13, 0x0D, 0xED, 0x0E, 0xB0, 0xFE, 0x4E, 0x48, 0x51, 0x38, 0x90, 0x01, 0x60, 0x61, 0xF3, 0x10, 0x98, 0xFB, 0xDF, 0x13, 0x76, 0x3A, 0x70, 0x6F, 0x1E, 0x05, 0x13, 0xB1, 0x77, 0x8F, 0xDF, 0x37, 0xA3, 0x96, 0xFD, 0xFA, 0x05, 0xFE, 0x6E, 0xAA, 0xBB, 0x12, 0x12, 0xE6, 0x89, 0xAD, 0xCA, 0x20, 0x0D, 0x4C, 0x35, 0x08, 0xFF, 0xC7, 0x92, 0x68, 0x9D, 0x5B, 0xAC, 0x38, 0xA2, 0x7C, 0x04, 0x2B, 0x2F, 0x02, 0x99, 0x81, 0x17, 0x97, 0xC4, 0x92, 0xF7, 0xD8, 0x6F, 0xCE, 0x91, 0x6F, 0x71, 0x5F, 0x31, 0xB4, 0x2F, 0xCC, 0x14, 0x64, 0xA4, 0x32, 0xC0, 0xE5, 0xF1, 0xA0, 0x34, 0xBD, 0x60, 0x87, 0x9A, 0x12, 0x2B, 0x2C, 0xCC, 0x83, 0xEE, 0x99, 0x4A, 0x3E, 0x5A, 0xB5, 0x94, 0x3F, 0xD1, 0x3C, 0x50, 0xB9, 0xAF, 0x1F, 0xFF, 0x8B, 0xB0, 0xAE, 0xF7, 0xC4, 0x1A, 0xFE, 0x8A, 0x95, 0x25, 0x72, 0xAA, 0x23, 0x88, 0x49, 0x98, 0xB3, 0x1D, 0x28, 0x6C, 0xC6, 0x8B, 0xA9, 0x47, 0x33, 0x65, 0xAE, 0xFA, 0x1F, 0xBF, 0x72, 0x2F, 0x0D, 0xBF, 0x33, 0xB4, 0x4B, 0x33, 0x65, 0x08, 0xD6, 0x17, 0x35, 0x8F, 0x75, 0xC9, 0xDF, 0xF4, 0xB7, 0xC2, 0x1A, 0x8F, 0x4D, 0x06, 0x5F, 0x22, 0x2C, 0x62, 0x2E, 0x80, 0x92, 0x9F, 0xF5, 0xF5, 0x09, 0xFA, 0xEE, 0xDB, 0x52, 0xBD, 0x8E, 0x6B, 0x6B, 0x68, 0xD1, 0xBF, 0xFD, 0x9B, 0x51, 0xF6, 0x2B, 0xEC, 0xE4, 0x8C, 0x1D, 0x36, 0x21, 0xCA, 0x08, 0x50, 0x4D, 0x3A, 0xE1, 0x6B, 0x0F, 0x75, 0xC7, 0xC9, 0xC8, 0x76, 0xA1, 0x7D, 0xCD, 0xCD, 0x91, 0x20, 0x65, 0xE6, 0x5E, 0xD9, 0x1A, 0x1A, 0xBD, 0xA5, 0x5D, 0xB9, 0xEA, 0x9D, 0x09, 0xC3, 0x80, 0x45, 0xAD, 0x29, 0x25, 0x4A, 0xAC, 0x9B, 0xFF, 0xBF, 0x43, 0xFC, 0x95, 0x9F, 0x58, 0x66, 0xDB, 0x30, 0xB6, 0xDD, 0x16, 0x3D, 0x18, 0xC2, 0x6B, 0x3D, 0xDB, 0xC0, 0xDC, 0xFC, 0x13, 0xF8, 0x6A, 0xF3, 0x4B, 0x7D, 0x27, 0x14, 0xE7, 0xE5, 0xE5, 0xC2, 0xDF, 0xE6, 0xB3, 0x54, 0xCD, 0x89, 0x30, 0xE3, 0x91, 0x2F, 0xEE, 0x61, 0x9D, 0x60, 0x06, 0xC6, 0x8F, 0x32, 0x74, 0x99, 0x18, 0x44, 0xF8, 0xFE, 0xD8, 0xED, 0xC5, 0x55, 0x29, 0x2C, 0x94, 0x90, 0x96, 0x3E, 0x3D, 0x3C, 0x56, 0xDB, 0xC1, 0xD5, 0xEC, 0x86, 0xFF, 0x86, 0x71, 0xCE, 0xFE, 0x59, 0xC2, 0x33, 0x89, 0x6D, 0xF3, 0x46, 0x88, 0x53, 0xA6, 0xF7, 0x8A, 0x57, 0xF8, 0x0D, 0x1A, 0xD6, 0x8C, 0xD7, 0x44, 0xAF, 0xC6, 0xFF, 0x1E, 0x98, 0x6B, 0xE3, 0x0A, 0xBA, 0x87, 0xEA, 0x02, 0xA9, 0x97, 0x2D, 0x5E, 0x16, 0x81, 0x99, 0xBA, 0xD7, 0x82, 0x5F, 0xCC, 0x1A, 0xDB, 0x79, 0xAB, 0xAD, 0xB4, 0x1F, 0x48, 0x46, 0xCD, 0x06, 0x95, 0xF1, 0xFB, 0x2F, 0xA4, 0x82, 0x03, 0x2B, 0x07, 0xF0, 0x84, 0xEF, 0x93, 0xE7, 0x27, 0x0D, 0xA6, 0x25, 0x02, 0x5E, 0xC2, 0x07, 0xAE, 0x9C, 0xDA, 0x36, 0x03, 0x48, 0xB3, 0x4A, 0xE3, 0x85, 0x8C, 0x60, 0x9E, 0x7D, 0x8E, 0x1C, 0x04, 0x23, 0xE6, 0xD1, 0xCE, 0x3E, 0x89, 0xEA, 0x75, 0xA6, 0xF0, 0x26, 0x3D, 0xD2, 0x84, 0x30, 0x75, 0x8B, 0xD2, 0xA4, 0x76, 0x79, 0x7A, 0x3A, 0x5A, 0x4B, 0xEC, 0xE7, 0x88, 0xC7, 0xCA, 0x9B, 0x65, 0x79, 0xDF, 0x04, 0x56, 0xD1, 0x42, 0x69, 0x04, 0xAB, 0xA7, 0xC1, 0x21, 0xE4, 0x74, 0xA1, 0x6E, 0x9D, 0x0D, 0x75, 0x68, 0x81, 0x58, 0x58, 0x62, 0x9C, 0x68, 0x99, 0xC2, 0xB2, 0x0E, 0x2A, 0x66, 0xD0, 0x01, 0xB2, 0x26, 0xA3, 0x60, 0x4F, 0xBB, 0x53, 0xE3, 0xDC, 0x63, 0xC0, 0xB2, 0x50, 0xFF, 0x55, 0x39, 0x1D, 0x70, 0x82, 0x22, 0xE1, 0xEB, 0x6C, 0x98, 0x52, 0xC2, 0xE1, 0xC4, 0xB7, 0x76, 0x7C, 0x0D, 0xA4, 0xB4, 0xD7, 0x64, 0x44, 0x9F, 0xE2, 0xA5, 0xCC, 0x24, 0x64, 0x9E, 0x67, 0x9D, 0xAA, 0x1D, 0xE5, 0x9F, 0x4A, 0x47, 0x3F, 0x7F, 0x76, 0x30, 0xA9, 0xEE, 0xC7, 0xFA, 0xAA, 0xAA, 0xB2, 0x33, 0x3E, 0x0E, 0x26, 0x8A, 0xA3, 0xC9, 0x03, 0x41, 0x2A, 0xF2, 0xEA, 0x21, 0xE5, 0xE1, 0x59, 0xCA, 0xDD, 0xF1, 0x74, 0x15, 0xB5, 0xC4, 0xED, 0x96, 0x7E, 0x52, 0xA5, 0xCF, 0x0E, 0x3F, 0xDE, 0x0D, 0x39, 0x19, 0x67, 0x99, 0x04, 0xC1, 0x45, 0x21, 0x20, 0xCA, 0x57, 0x9B, 0x29, 0x0F, 0x79, 0xED, 0xC2, 0xB9, 0xBF, 0x29, 0xA2, 0xCA, 0x30, 0xF9, 0xE6, 0x09, 0xAB, 0x58, 0x11, 0x63, 0x15, 0x18, 0xD3, 0x18, 0xFF, 0xF6, 0xD5, 0x23, 0xCC, 0x91, 0x96, 0x25, 0x40, 0x35, 0xDA, 0x4D, 0xB6, 0x85 }; - public static readonly byte[] BH3SBox = new byte[] { 0x75, 0x45, 0xC7, 0x35, 0x7E, 0x7B, 0x46, 0x29, 0xE7, 0x10, 0xC1, 0xEB, 0x52, 0xCA, 0xC2, 0xA0, 0x0D, 0xCC, 0x31, 0xA7, 0xA8, 0x44, 0x07, 0x4C, 0x93, 0x6E, 0xFC, 0x0E, 0xF9, 0xFB, 0xDD, 0xAA, 0x4A, 0x84, 0x18, 0xD9, 0x2C, 0x09, 0x21, 0x13, 0x15, 0xBB, 0x37, 0x8E, 0xE2, 0x77, 0x60, 0x22, 0xE8, 0x06, 0x00, 0xA3, 0x56, 0xB7, 0xE9, 0xF1, 0x1B, 0xCB, 0x40, 0xC9, 0x7C, 0xC5, 0xE6, 0xF5, 0xC3, 0x0A, 0x69, 0x5E, 0x9C, 0x39, 0x11, 0x5F, 0xA2, 0xC0, 0xDB, 0x32, 0x8A, 0x3A, 0x63, 0xD8, 0x3F, 0x1A, 0xCE, 0xC6, 0x6C, 0xB3, 0x08, 0x59, 0x64, 0x14, 0x4D, 0x05, 0xD5, 0x34, 0x19, 0x2B, 0x4E, 0x3B, 0x99, 0x1F, 0xD2, 0x28, 0xAF, 0xEF, 0xE0, 0x95, 0x2D, 0xE3, 0xAB, 0x5D, 0x71, 0x53, 0x3E, 0x04, 0x47, 0x25, 0xD7, 0xF8, 0xAC, 0x8C, 0xB2, 0x9A, 0xA9, 0x9F, 0xF7, 0x88, 0xDA, 0x27, 0x9D, 0x89, 0x43, 0x0B, 0x24, 0xBD, 0x26, 0x38, 0x6A, 0xA5, 0x1C, 0xD0, 0xEE, 0x62, 0x67, 0x23, 0x9B, 0xEA, 0xDE, 0x72, 0x6D, 0x80, 0x1E, 0x3D, 0x0F, 0x2E, 0x54, 0xFF, 0x3C, 0x1D, 0xF0, 0x03, 0x5A, 0x65, 0xBC, 0x30, 0x61, 0x57, 0x6B, 0xBF, 0xA6, 0x58, 0x76, 0x2F, 0x01, 0xA1, 0x20, 0xD3, 0x74, 0x2A, 0x97, 0x8F, 0x87, 0x50, 0xAE, 0xDF, 0x55, 0xF3, 0x7F, 0xB0, 0xD6, 0x41, 0xE4, 0x4B, 0x02, 0x86, 0x16, 0x85, 0x7D, 0xBA, 0x0C, 0xD4, 0xFE, 0x7A, 0xC4, 0x51, 0x8D, 0x78, 0xCD, 0x33, 0xE1, 0x98, 0xAD, 0x79, 0x68, 0xB6, 0x17, 0xFD, 0xC8, 0x82, 0x6F, 0x4F, 0xD1, 0x8B, 0xE5, 0x66, 0xFA, 0x91, 0xB5, 0x42, 0x5C, 0x49, 0xB9, 0x73, 0xF6, 0x5B, 0x36, 0xB8, 0xB4, 0xB1, 0xEC, 0x90, 0x81, 0x92, 0xF2, 0xF4, 0x94, 0x83, 0x96, 0x9E, 0x48, 0xBE, 0xDC, 0xED, 0xCF, 0xA4, 0x70, 0x12, 0xA7, 0xA6, 0xF8, 0xF0, 0xD9, 0x1B, 0x85, 0xF4, 0xA9, 0x36, 0xA2, 0xE6, 0xCB, 0xCF, 0x9C, 0x2E, 0x78, 0xCE, 0x67, 0x07, 0x50, 0xF2, 0x0B, 0x2B, 0xB8, 0xA4, 0x1E, 0x28, 0xD7, 0x17, 0x5F, 0x74, 0xC8, 0xDA, 0x2C, 0x86, 0xAD, 0xBB, 0xD8, 0xFB, 0x6C, 0x1A, 0x8F, 0x0C, 0xE4, 0x97, 0x13, 0x2D, 0xB2, 0x5B, 0x65, 0x49, 0x45, 0x7C, 0x7B, 0x38, 0xDE, 0xAC, 0x58, 0x2F, 0x33, 0xD2, 0x52, 0x14, 0x02, 0x9D, 0xF5, 0x6A, 0x43, 0x87, 0xE0, 0x18, 0x69, 0x5E, 0x68, 0xE9, 0xAE, 0xF9, 0x63, 0xBC, 0xBF, 0xC2, 0x94, 0xB4, 0x30, 0xE8, 0x23, 0x0F, 0x64, 0x26, 0x80, 0xB3, 0x8D, 0xC1, 0xE3, 0x15, 0x34, 0x05, 0xC9, 0x29, 0xE2, 0xA8, 0x55, 0xD0, 0x37, 0xDC, 0xF6, 0xBA, 0x0D, 0x8B, 0x8E, 0x60, 0xEA, 0x84, 0x90, 0x48, 0x79, 0x10, 0x9F, 0x1F, 0x8A, 0xBD, 0xFD, 0x39, 0x04, 0x3F, 0xB9, 0x4C, 0x75, 0x3B, 0x22, 0x46, 0x7F, 0xDB, 0x2A, 0x0E, 0x35, 0x40, 0xED, 0xFC, 0x47, 0xB1, 0x7D, 0xD4, 0x62, 0x9E, 0x5D, 0xC5, 0x51, 0xA1, 0x88, 0x89, 0x11, 0x31, 0xC4, 0xFE, 0x27, 0x99, 0x5A, 0x3A, 0x91, 0x81, 0x95, 0x70, 0x1D, 0x12, 0x98, 0x4F, 0x20, 0x92, 0x56, 0x6D, 0xD5, 0xE5, 0xEC, 0xAA, 0xC0, 0xA3, 0x9A, 0x06, 0x32, 0xEE, 0x3D, 0x53, 0x08, 0xD3, 0x3E, 0xDF, 0xE1, 0xA0, 0xC6, 0xB7, 0x03, 0x6B, 0x59, 0xA5, 0x6F, 0x09, 0xD1, 0x93, 0x54, 0xF3, 0x77, 0xC7, 0xBE, 0x8C, 0xE7, 0x25, 0x76, 0x41, 0x71, 0x72, 0xCC, 0x9B, 0x16, 0x7E, 0x4B, 0x44, 0xAF, 0xF7, 0xCD, 0xAB, 0xB0, 0x7A, 0x57, 0xB5, 0x66, 0xEF, 0xEB, 0xFF, 0xB6, 0x00, 0x4E, 0xCA, 0x61, 0xC3, 0xF1, 0x4D, 0x21, 0x1C, 0xDD, 0x0A, 0xD6, 0x4A, 0x5C, 0x42, 0x83, 0x6E, 0x96, 0x19, 0x01, 0x73, 0x3C, 0xFA, 0x24, 0x82, 0x5D, 0x33, 0x3A, 0x97, 0x9D, 0xCE, 0x65, 0x39, 0xFB, 0xEB, 0x51, 0xC1, 0x59, 0x1C, 0xAF, 0x09, 0x27, 0x57, 0xA0, 0xD4, 0x75, 0xCF, 0xF9, 0x8A, 0x3C, 0xAA, 0x6E, 0x6C, 0xE8, 0xDF, 0x12, 0x2A, 0x1D, 0x02, 0xB4, 0x8C, 0x0C, 0xF7, 0x4A, 0xBD, 0xF4, 0x71, 0x16, 0xC2, 0x13, 0x86, 0x50, 0x2D, 0xA7, 0x28, 0x4B, 0x03, 0x17, 0x00, 0x15, 0x25, 0x7C, 0x19, 0xFE, 0x23, 0xF2, 0x0E, 0xC3, 0x9A, 0x0A, 0x1E, 0xF8, 0x7E, 0x70, 0x0B, 0x9E, 0x2C, 0xF3, 0xC9, 0xE4, 0xAE, 0x2E, 0x89, 0x4E, 0xA8, 0x87, 0xD9, 0x7A, 0x18, 0xDB, 0x04, 0xF0, 0xBB, 0x83, 0x8D, 0xE0, 0x92, 0x5F, 0x2B, 0x3E, 0xC0, 0xD5, 0xB6, 0x38, 0x76, 0xC5, 0x4C, 0x29, 0x36, 0x53, 0x41, 0x4D, 0x1F, 0x11, 0x4F, 0xBC, 0xD0, 0xDC, 0x96, 0x24, 0xEC, 0x9F, 0x47, 0x22, 0x6B, 0xCA, 0x56, 0x42, 0xEF, 0x99, 0x7D, 0x43, 0x63, 0x0F, 0xB8, 0x48, 0xAC, 0x55, 0xE1, 0x5E, 0xED, 0xC6, 0xD3, 0xD6, 0x40, 0x3D, 0xA5, 0x44, 0x30, 0xFC, 0xD2, 0x69, 0x32, 0xF6, 0x64, 0x01, 0x46, 0x34, 0xD1, 0xA9, 0x6D, 0x5A, 0x80, 0x35, 0xBA, 0x9C, 0x79, 0xCB, 0x61, 0x78, 0x08, 0x3F, 0x14, 0x8F, 0x94, 0xE3, 0x2F, 0xC8, 0x77, 0x54, 0x49, 0xA2, 0xFF, 0xE2, 0x6A, 0xB0, 0xD7, 0xDD, 0x5B, 0x68, 0xB2, 0x81, 0xA4, 0x1B, 0x05, 0xAB, 0x88, 0xFD, 0x20, 0xB7, 0x93, 0x7B, 0x37, 0xB1, 0x9B, 0xF5, 0xB9, 0xAD, 0xB5, 0x45, 0x73, 0xC4, 0xBE, 0x67, 0x8E, 0x1A, 0x07, 0xE6, 0x58, 0x3B, 0xEA, 0xA3, 0xC7, 0x85, 0x6F, 0x74, 0x8B, 0x60, 0x7F, 0xCD, 0x62, 0xE7, 0xE5, 0xA1, 0x10, 0xF1, 0xDE, 0x21, 0x72, 0x5C, 0x91, 0x31, 0x95, 0xDA, 0x90, 0x26, 0x52, 0xA6, 0xE9, 0x0D, 0xFA, 0x84, 0x98, 0x82, 0xB3, 0x06, 0xD8, 0xEE, 0x66, 0xCC, 0xBF, 0x35, 0x99, 0xD2, 0xA3, 0xC4, 0x83, 0x50, 0xC5, 0x7C, 0x54, 0xB0, 0x27, 0x68, 0xF7, 0xBD, 0xCA, 0x79, 0x08, 0x94, 0x85, 0x6B, 0xC2, 0xC8, 0xEF, 0x46, 0xF8, 0xC6, 0xA1, 0x29, 0x57, 0xD5, 0x5B, 0x11, 0x6F, 0x0F, 0xB6, 0xF9, 0x87, 0xAC, 0xD3, 0x1E, 0x84, 0xFD, 0x43, 0x09, 0xA2, 0x28, 0x56, 0xA0, 0xAD, 0x81, 0x55, 0x98, 0x97, 0x78, 0xE9, 0xDF, 0x1F, 0x2E, 0xE7, 0x9D, 0x59, 0x01, 0x1C, 0x52, 0x88, 0x62, 0x5D, 0x31, 0x30, 0x6D, 0x38, 0x2C, 0x24, 0x32, 0x26, 0x6E, 0xF1, 0x4C, 0x7D, 0x1D, 0x74, 0x7F, 0xC9, 0xD1, 0xD6, 0xB8, 0x51, 0xF5, 0x8D, 0x9A, 0x8F, 0xB5, 0xB3, 0xB2, 0x47, 0x3C, 0x1A, 0x8A, 0xDD, 0xF3, 0xDA, 0x5A, 0xC0, 0xD4, 0x07, 0x12, 0x53, 0x45, 0x93, 0xAB, 0xCB, 0x67, 0x48, 0x00, 0x8C, 0xE1, 0x40, 0x2F, 0x6C, 0x17, 0x22, 0xBA, 0xF4, 0xE5, 0xD7, 0x3E, 0x7E, 0x5E, 0xF6, 0x37, 0x39, 0x20, 0xA4, 0x4A, 0xCC, 0x0A, 0x03, 0x10, 0x33, 0x36, 0x9F, 0x2A, 0x70, 0x5C, 0x9C, 0xFE, 0x0D, 0x41, 0xDE, 0x49, 0x3D, 0x92, 0x89, 0xDB, 0x05, 0x6A, 0x23, 0xE0, 0x8E, 0x8B, 0xAA, 0x77, 0x69, 0x63, 0x0C, 0x2D, 0xA7, 0x14, 0x3F, 0xEB, 0xF0, 0xCD, 0x3B, 0x4B, 0xAE, 0x2B, 0xFA, 0xFB, 0x86, 0x58, 0x9B, 0x34, 0x7A, 0x95, 0xC3, 0x16, 0x96, 0xE3, 0x1B, 0xB7, 0x02, 0x44, 0x4F, 0xAF, 0xBF, 0xFC, 0xB1, 0x13, 0xEE, 0x72, 0x06, 0xD0, 0x04, 0x0B, 0xA8, 0x80, 0xBC, 0x5F, 0x65, 0xDC, 0xE2, 0x60, 0x7B, 0xBB, 0xBE, 0x4D, 0x61, 0xCE, 0xB4, 0x82, 0x18, 0xD9, 0xC7, 0x76, 0x73, 0x66, 0xC1, 0xA5, 0xFF, 0xCF, 0xEA, 0x75, 0xE8, 0x9E, 0x3A, 0xA9, 0xE6, 0x4E, 0x71, 0x21, 0x15, 0x25, 0xF2, 0xE4, 0xB9, 0xA6, 0x19, 0x42, 0x90, 0x0E, 0xEC, 0xED, 0x91, 0x64, 0xD8 }; - public static readonly byte[] BH3ExpansionKey = new byte[] { 0x87, 0xA5, 0x7F, 0xFA, 0x75, 0x53, 0x8B, 0x29, 0xA9, 0x72, 0x62, 0x68, 0xAD, 0x4D, 0x83, 0x81, 0x0A, 0xB1, 0x2E, 0xAA, 0x63, 0x88, 0xF2, 0x18, 0x6C, 0xB2, 0xBC, 0xDC, 0x4A, 0x95, 0x30, 0x07, 0x81, 0x1D, 0xEF, 0x5E, 0x16, 0xC3, 0x9B, 0x86, 0x77, 0x8F, 0xEC, 0x0E, 0x2A, 0x22, 0xF1, 0x6B, 0x52, 0x79, 0xD6, 0xEB, 0xF0, 0xC8, 0xD8, 0x0C, 0x72, 0x92, 0xDD, 0x57, 0xE1, 0xF8, 0x42, 0x2B, 0x5E, 0x44, 0x44, 0x48, 0x9A, 0xC6, 0x21, 0x6E, 0xED, 0x44, 0xE8, 0x35, 0x11, 0x5C, 0x93, 0x73, 0xA5, 0x9C, 0xA1, 0x67, 0x29, 0x51, 0x62, 0xEE, 0xE7, 0x15, 0x85, 0xBE, 0xAD, 0x20, 0x28, 0xAB, 0x17, 0xEE, 0xE4, 0x90, 0x3A, 0x7A, 0xCE, 0x28, 0xAC, 0xBF, 0xAB, 0xD0, 0xAB, 0xA2, 0xCE, 0x22, 0x47, 0x97, 0x8B, 0xA2, 0xE9, 0x47, 0x0C, 0x38, 0x3C, 0xBB, 0xBA, 0x51, 0xBE, 0x4F, 0xAD, 0xDE, 0x3A, 0xC5, 0x02, 0xDD, 0xB3, 0x50, 0x8B, 0xBA, 0xC6, 0x3E, 0xC2, 0xFD, 0xA7, 0xB8, 0x90, 0xC1, 0x82, 0x6F, 0x82, 0xBF, 0xCC, 0x4D, 0xA3, 0xF0, 0xCB, 0xAC, 0x49, 0x42, 0x8B, 0xFC, 0xFC, 0x8B, 0xDD, 0x3D, 0xA4, 0x11, 0x2F, 0x18, 0x17, 0xB2, 0x62, 0x2B, 0x5A, 0xB6, 0x64, 0xF7, 0xB3, 0xC9 }; - public static readonly byte[] BH3ConstKey = new byte[] { 0x28, 0x20, 0x24, 0xC9, 0x95, 0x36, 0x70, 0x22, 0xFF, 0x23, 0x0A, 0x03, 0x3F, 0x5D, 0xD0, 0x88 }; - - public static readonly byte[] Mr0kExpansionKey = new byte[] { 0x2F, 0xE0, 0x89, 0x14, 0xE8, 0x23, 0x4E, 0xE6, 0x91, 0x6D, 0xED, 0xED, 0x86, 0x62, 0x85, 0x1C, 0xD7, 0x0F, 0x87, 0x2B, 0x64, 0xF3, 0xE0, 0x40, 0xDC, 0x27, 0x17, 0x4C, 0xC2, 0x73, 0x4E, 0x6D, 0x00, 0xE7, 0x91, 0x04, 0x4E, 0x14, 0x60, 0x8D, 0x1A, 0xE8, 0x36, 0x4F, 0xCF, 0xFB, 0x50, 0xA7, 0x5D, 0x89, 0x51, 0x7B, 0xBB, 0xEB, 0x4F, 0x1E, 0x56, 0xA0, 0xB0, 0x1F, 0x48, 0x67, 0x86, 0x21, 0x31, 0xF8, 0xA2, 0xB5, 0xED, 0x90, 0xA4, 0x46, 0xF1, 0x4E, 0x36, 0x38, 0x63, 0x03, 0xA9, 0x8C, 0x05, 0xD3, 0x2B, 0x17, 0xB2, 0x18, 0x93, 0x34, 0xE0, 0xAA, 0x63, 0x2E, 0x39, 0x99, 0x7D, 0x08, 0x33, 0x0C, 0x3F, 0xB0, 0x07, 0xEE, 0xD2, 0xB6, 0x8E, 0x0A, 0xB4, 0x3D, 0xA6, 0xBF, 0x77, 0xAF, 0xBE, 0x17, 0x83, 0xC0, 0x83, 0x2A, 0x57, 0x83, 0xB2, 0xA8, 0xF7, 0xA3, 0xDE, 0xE6, 0x58, 0x4C, 0xA5, 0x33, 0xF1, 0xE0, 0x9B, 0x3D, 0x7B, 0xC7, 0x26, 0x0B, 0x0E, 0x87, 0xAA, 0x10, 0xB8, 0x5B, 0xCD, 0x9D, 0x01, 0x0B, 0x64, 0x92, 0xA8, 0xE4, 0xDE, 0x76, 0xA8, 0xE3, 0xAD, 0xA2, 0xC6, 0xB9, 0x79, 0xBC, 0xEC, 0xF7, 0x37, 0xCF, 0x6C, 0x3D, 0x0D, 0x68, 0xB1, 0x1E, 0xFC, 0x38, 0x43, 0x85 }; - public static readonly byte[] Mr0kKey = new byte[] { 0xA1, 0x55, 0x38, 0x57, 0xD0, 0xFA, 0x09, 0xEC, 0xB6, 0x74, 0x76, 0xC7, 0x60, 0x0A, 0xF1, 0x6C, 0x4C, 0x45, 0xDC, 0x03, 0x80, 0x18, 0x94, 0xDB, 0x75, 0x2E, 0x35, 0xBF, 0x74, 0x29, 0xAE, 0x2D, 0xFA, 0x37, 0x1A, 0x83, 0x05, 0xAB, 0x2A, 0x47, 0xB8, 0x4D, 0x88, 0xBF, 0xD3, 0x31, 0x96, 0x53, 0xCB, 0xA9, 0x81, 0xD4, 0xAF, 0x3D, 0xE3, 0xBA, 0xC7, 0x84, 0x23, 0xD2, 0xEC, 0xB2, 0xD7, 0x02, 0x4F, 0xC2, 0x45, 0xF4, 0x53, 0x56, 0x6E, 0xD6, 0xA6, 0xE8, 0x8C, 0x1D, 0xAE, 0x22, 0x0B, 0x75, 0xE6, 0xE7, 0x82, 0x88, 0x06, 0x61, 0xB8, 0x4B, 0xA3, 0xCE, 0x52, 0x02, 0x5C, 0x20, 0xE0, 0x19, 0x03, 0x08, 0xD2, 0x4B, 0x84, 0xF4, 0x11, 0x41, 0xC9, 0xF7, 0xE0, 0x0D, 0x86, 0x09, 0x45, 0xF0, 0xF2, 0x31, 0xE2, 0x88, 0xC6, 0xE3, 0x3E, 0x40, 0x17, 0x3A, 0xC0, 0x0C, 0x81, 0x8A, 0x80, 0xC3, 0x76, 0xA4, 0x85, 0x2D, 0x55, 0xB9, 0x6D, 0x32, 0x31, 0xA3, 0xBB, 0xEC, 0xB4, 0x50, 0xA5, 0x7E, 0xA4, 0x87, 0xEA, 0x5B, 0x9A, 0x67, 0x6C, 0xE0, 0x53, 0x4D, 0x58, 0x29, 0x84, 0x99, 0x83, 0xB0, 0x04, 0x0A, 0x43, 0x9C, 0xF6, 0xB8, 0x57, 0x5C, 0x68, 0x34, 0x60, 0x36, 0xE6, 0x73, 0x8C, 0xA8, 0x00, 0xA7, 0x64, 0x91, 0xBE, 0xBE, 0x6F, 0x1E, 0x7B, 0x57, 0x41, 0xB8, 0xAF, 0x13, 0x29, 0x87, 0x27, 0xE1, 0x64, 0xB5, 0x46, 0xA6, 0xFA, 0x9E, 0x71, 0x15, 0x85, 0xB5, 0x0D, 0x00, 0x0D, 0xA9, 0x41, 0xFE, 0x1F, 0x05, 0xD8, 0xF2, 0xFA, 0x74, 0x9F, 0x3D, 0xE8, 0x61, 0xA5, 0x06, 0x0A, 0x8A, 0xC4, 0xF6, 0x64, 0x4F, 0xCE, 0x25, 0x72, 0x81, 0x34, 0xFA, 0x81, 0x0C, 0xC9, 0xC6, 0xF4, 0xA1, 0x28, 0x4F, 0x14, 0xD3, 0x0E, 0xE1, 0xDB, 0x86, 0xE1, 0x1E, 0x3A, 0xA9, 0xB3, 0xF1, 0x17, 0xDE, 0x6E, 0x9D, 0x5B, 0x08, 0x79, 0xE0, 0x93, 0x02, 0xF0, 0xAD, 0x2B, 0x21, 0x68, 0x7A, 0xC7, 0xFE, 0xEB, 0x1E, 0xD9, 0x8B, 0x2C, 0x85, 0xCE, 0x69, 0xDB, 0xDE, 0x6D, 0x30, 0x4B, 0x0E, 0x74, 0x9C, 0xC8, 0x2D, 0x8A, 0xE5, 0x0C, 0x10, 0x6B, 0xF1, 0x11, 0x41, 0x14, 0x69, 0xF9, 0x5F, 0x68, 0xB8, 0x6A, 0xD9, 0x0E, 0x03, 0x72, 0x9C, 0x5F, 0x35, 0x2E, 0xB0, 0x88, 0x66, 0x17, 0xB3, 0xE6, 0xCB, 0xF2, 0xF2, 0xC3, 0xE4, 0x80, 0x4F, 0x6D, 0x07, 0x15, 0x85, 0x31, 0x85, 0x78, 0xC2, 0x60, 0x2E, 0xB5, 0x7A, 0x16, 0xEE, 0x61, 0xEB, 0x9B, 0x33, 0x71, 0xBD, 0x19, 0x4A, 0xBA, 0xA9, 0x72, 0xA1, 0xEC, 0x32, 0xFF, 0x27, 0x79, 0x6F, 0x33, 0x2B, 0xC7, 0xC9, 0x88, 0x7B, 0x99, 0x6F, 0x34, 0xA2, 0xD1, 0x25, 0xC6, 0x8D, 0x91, 0xE7, 0xBA, 0x7E, 0xDD, 0x16, 0x7A, 0x3D, 0x39, 0xC3, 0x07, 0x3A, 0xD5, 0xE7, 0x0D, 0x48, 0xEB, 0x28, 0x46, 0xE0, 0xE8, 0x6E, 0x8F, 0xDF, 0xA4, 0x67, 0x82, 0x8E, 0x4E, 0x95, 0xE1, 0xA3, 0x27, 0x1F, 0x54, 0x47, 0x9D, 0x97, 0xA6, 0x21, 0x00, 0x2B, 0x84, 0xBF, 0xB8, 0x3D, 0x39, 0x74, 0x72, 0x22, 0x9B, 0xC2, 0xDB, 0xEE, 0x3A, 0x9C, 0x9B, 0xB2, 0x79, 0x3D, 0xBE, 0xAC, 0xAA, 0x63, 0x81, 0xC5, 0xC6, 0x22, 0x32, 0x70, 0x51, 0xC5, 0x30, 0xE6, 0x3A, 0x6B, 0xF0, 0xCF, 0x35, 0x3D, 0xA0, 0x24, 0xA7, 0xC4, 0x15, 0xA1, 0x78, 0x3B, 0xB1, 0xE0, 0xFE, 0x0C, 0xF5, 0x9B, 0xBD, 0xA1, 0x5B, 0x5F, 0xE8, 0xAF, 0x76, 0xB7, 0x11, 0x75, 0x12, 0xEF, 0x0A, 0xBF, 0xE9, 0xBF, 0xE2, 0x73, 0xED, 0x4A, 0xE5, 0x23, 0x82, 0xA4, 0xD0, 0x1C, 0x59, 0xCF, 0x8B, 0x24, 0xAB, 0xD8, 0x43, 0xFF, 0x30, 0x70, 0xFA, 0xB8, 0x38, 0x24, 0x5A, 0x50, 0x54, 0x13, 0xEB, 0x68, 0xDD, 0x98, 0xCC, 0xCB, 0x36, 0x65, 0x1A, 0x26, 0x8C, 0xB7, 0x7B, 0x3D, 0x5A, 0x75, 0xE2, 0xD3, 0x7F, 0x42, 0x91, 0xC1, 0xBD, 0x72, 0xFF, 0x7E, 0x18, 0xCC, 0x0D, 0x39, 0xE9, 0x2D, 0x7F, 0x46, 0x90, 0xF1, 0xBD, 0x0B, 0x09, 0x5D, 0xD0, 0x0D, 0xEF, 0xAD, 0x93, 0x52, 0xEB, 0x9A, 0x4B, 0x8D, 0x20, 0x27, 0xD8, 0xE1, 0xE6, 0x30, 0xFD, 0xE2, 0x08, 0xF3, 0x91, 0x61, 0x53, 0x55, 0xC8, 0x14, 0xAB, 0x19, 0x19, 0x4F, 0xF4, 0x05, 0xEA, 0xFE, 0x76, 0x48, 0xBA, 0xD2, 0xE6, 0x8B, 0x7A, 0xA2, 0x63, 0xE1, 0x3A, 0x10, 0xE4, 0x48, 0xEB, 0xA9, 0x3C, 0x61, 0x1E, 0x0C, 0x3D, 0x0E, 0x89, 0x2E, 0xCB, 0x83, 0xEC, 0x15, 0x8E, 0x9B, 0x4D, 0x9F, 0xB9, 0x22, 0xA2, 0x63, 0xAA, 0x59, 0x9F, 0x3E, 0x96, 0xEB, 0x4B, 0x4F, 0x71, 0x56, 0x15, 0xF2, 0xED, 0x5E, 0x7E, 0x10, 0x64, 0x66, 0x3C, 0xB8, 0x90, 0x7A, 0x76, 0x6E, 0x2F, 0x6B, 0x43, 0xAB, 0x49, 0x37, 0xBF, 0x42, 0x93, 0x4C, 0x61, 0x63, 0xF9, 0x92, 0x48, 0x2D, 0xEF, 0x73, 0x86, 0xCC, 0xAC, 0x44, 0x56, 0xC5, 0x53, 0x32, 0x17, 0x7E, 0x6F, 0x03, 0x0A, 0x6A, 0x7A, 0x68, 0x32, 0x83, 0xE8, 0xDD, 0x64, 0x96, 0x2C, 0x58, 0xB0, 0x12, 0xAC, 0x92, 0xCD, 0xFA, 0x86, 0x26, 0x69, 0xE3, 0xDF, 0xD8, 0xE9, 0x5A, 0x5C, 0xEF, 0x0E, 0xBE, 0x77, 0x22, 0xB5, 0xFE, 0xCA, 0x48, 0x67, 0x44, 0xD8, 0xBE, 0x44, 0xF2, 0x92, 0x9C, 0x60, 0x40, 0xFD, 0xE6, 0xC7, 0x80, 0x09, 0x6A, 0xCD, 0x16, 0x2E, 0xF7, 0x4B, 0x6A, 0x72, 0xE1, 0x96, 0x9B, 0xE4, 0x4E, 0x99, 0xD8, 0x7E, 0x37, 0x30, 0x6F, 0xB4, 0x07, 0x63, 0x1A, 0x2F, 0x9F, 0x29, 0xB6, 0x96, 0x08, 0x3A, 0x4C, 0x88, 0x97, 0x8B, 0x83, 0x9A, 0x0F, 0xF7, 0x0B, 0xCD, 0xF5, 0x69, 0x17, 0x69, 0x23, 0xC0, 0x50, 0x56, 0xC7, 0xA7, 0x66, 0x85, 0x68, 0x37, 0x32, 0xAE, 0x3A, 0x70, 0xB9, 0x80, 0xEF, 0x3C, 0x28, 0xF9, 0xFF, 0xC4, 0x17, 0xDA, 0x61, 0xB2, 0x35, 0x5D, 0xBE, 0x87, 0x7C, 0x0B, 0x9F, 0x9E, 0x8A, 0x26, 0x88, 0xA0, 0xB9, 0x2B, 0x90, 0x5E, 0x69, 0x50, 0xFE, 0x16, 0x78, 0x96, 0x12, 0xD8, 0xFE, 0x2B, 0xEA, 0xA1, 0xB3, 0x89, 0x20, 0x1F, 0xB2, 0x59, 0x3A, 0x6A, 0x25, 0x2E, 0xA5, 0xA7, 0x6B, 0x93, 0x5C, 0xC7, 0x91, 0x89, 0xCF, 0x99, 0xEC, 0x5A, 0xAF, 0xCB, 0x8D, 0xC6, 0x79, 0x75, 0x79, 0x32, 0x8A, 0xE0, 0x9A, 0x04, 0xCB, 0xB0, 0x57, 0xB8, 0x75, 0x81, 0xFB, 0x65, 0x1B, 0xFC, 0xB2, 0xA0, 0x9B, 0xCE, 0xD7, 0x5D, 0x1D, 0x06, 0xDB, 0x6C, 0x46, 0x55, 0x7C, 0xBC, 0x45, 0x15, 0x2D, 0xBF, 0xC8, 0x0D, 0xB7, 0x02, 0x33, 0x54, 0x16, 0x14, 0xE4, 0xE3, 0xE1, 0xDF, 0x86, 0x80, 0x7F, 0x4C, 0xE8, 0x8D, 0xA3, 0x97, 0x99, 0xBB, 0x2E, 0x7A, 0x69, 0x60, 0x12, 0x58, 0x71, 0xF4, 0x50, 0xD1, 0xB2, 0xB0, 0x2E, 0x63, 0x29, 0x3A, 0x63, 0x57, 0x09, 0x99, 0x1A, 0x98, 0x39, 0x54, 0x65, 0x94, 0x06, 0xD3, 0xC3, 0x31, 0x99, 0x04, 0xD8, 0xAB, 0x5A, 0x3F, 0xA4, 0xBB, 0xE2, 0x6E, 0x79, 0x70, 0x4D, 0x7A, 0x87, 0x1D, 0x70, 0x55, 0xB0, 0xA6, 0x65, 0x20, 0x44, 0x54, 0x8D, 0x14, 0x33, 0x78, 0x4D, 0x24, 0x0A, 0x67, 0xBB, 0xE9, 0x3E, 0xE7, 0xCA, 0x5E, 0x98, 0x26, 0x49, 0x11, 0x9F, 0xE0, 0x0B, 0xAB, 0x03, 0xD0, 0x0C, 0xD3, 0x38, 0xCA, 0xA0, 0xEF, 0xD9, 0x59, 0xAA, 0x1F, 0xA0, 0x72, 0x8C, 0xC9, 0xBA, 0x99, 0x9D, 0x6F, 0x6B, 0x42, 0x79, 0x3A, 0x9F, 0x3B, 0xBB, 0x9D, 0x22, 0x88, 0xD5, 0x01, 0x93, 0x2F, 0xC4, 0x23, 0x16, 0xD0, 0xA6, 0x35, 0xA3 }; - public static readonly byte[] Mr0kConstKey = new byte[] { 0xA1, 0xF2, 0x7E, 0xB3, 0x5E, 0xDC, 0x88, 0xC7, 0xB6, 0x6C, 0xD8, 0x76, 0xD6, 0x7B, 0xB2, 0x69 }; - - public static readonly byte[] MarkKey = new byte[] { 0x71, 0x98, 0xAA, 0xE6, 0xCE, 0x1B, 0x05, 0x4A, 0xE9, 0xFF, 0x45, 0x21, 0xC3, 0x38, 0x5E, 0x3C, 0x0F, 0xFB, 0xF5, 0xBB, 0xF6, 0x81, 0x48, 0x15, 0xFA, 0xD7, 0x77, 0x35, 0x82, 0x17, 0xD9, 0x9D, 0x56, 0x28, 0x2E, 0xA9, 0x51, 0xBA, 0x66, 0x2F, 0x22, 0xDD, 0xBB, 0x8A, 0x3B, 0xAD, 0x90, 0x63, 0xC6, 0x64, 0xFB, 0xD6, 0xCF, 0xA8, 0xBC, 0x48, 0x02, 0xC3, 0xBE, 0x36, 0xB2, 0x93, 0xBC, 0xD9 }; - - public static readonly byte[] ToTBlockKey = { 0x25, 0x7D, 0x02, 0x00, 0x41, 0xC8, 0x03, 0x00, 0x73, 0xA7, 0x05, 0x00, 0xBF, 0x44, 0x07, 0x00, 0xDD, 0x90, 0x08, 0x00, 0xDF, 0x69, 0x0A, 0x00 }; - - private static int GF256Mul(int a, int b) => (a == 0 || b == 0) ? 0 : GF256Exp[(GF256Log[a] + GF256Log[b]) % 0xFF]; - private static void DescrambleChunk(byte[] input, int offset) - { - byte[] vector = new byte[0x10]; - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 0x10; j++) - { - int k = Mhy0ShiftRow[(2 - i) * 0x10 + j]; - int idx = j % 8; - vector[j] = (byte)(Mhy0Key[idx] ^ GISBox[(j % 4 * 0x100) | GF256Mul(Mhy0Mul[idx], input[offset + k])]); - } - Buffer.BlockCopy(vector, 0, input, offset, 0x10); - } - } - private static byte[] Descramble(byte[] input, ulong blockSize, ulong entrySize) - { - var roundedEntrySize = (int)((entrySize + 0xF) / 0x10 * 0x10); - for (int i = 0; i < roundedEntrySize; i += 0x10) - DescrambleChunk(input, i + 4); - - for (int i = 0; i < 4; i++) - input[i] ^= input[i + 4]; - - ulong currentEntry = (ulong)roundedEntrySize + 4; - var finished = false; - while (currentEntry < blockSize && !finished) - { - for (ulong i = 0; i < entrySize; i++) - { - input[i + currentEntry] ^= input[i + 4]; - if (i + currentEntry >= blockSize - 1) - { - finished = true; - break; - } - } - currentEntry += entrySize; - } - - return input; - } - public static byte[] DescrambleHeader(byte[] input) => Descramble(input, 0x39, 0x1C); - public static byte[] DescrambleEntry(byte[] input) => Descramble(input, (ulong)Math.Min(input.Length, 0x21), 8); - } -} diff --git a/AssetStudio/Game/Crypto/Mark.cs b/AssetStudio/Game/Crypto/Mark.cs deleted file mode 100644 index 5ce12bb..0000000 --- a/AssetStudio/Game/Crypto/Mark.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.IO; - -namespace AssetStudio -{ - public static class Mark - { - private const string Signature = "mark"; - private const int BlockSize = 0xA00; - private const int ChunkSize = 0x264; - private const int ChunkPadding = 4; - - private static readonly int BlockPadding = ((BlockSize / ChunkSize) + 1) * ChunkPadding; - private static readonly int ChunkSizeWithPadding = ChunkSize + ChunkPadding; - private static readonly int BlockSizeWithPadding = BlockSize + BlockPadding; - - public static byte[] Decrypt(FileReader reader) - { - var signature = reader.ReadStringToNull(4); - if (signature != Signature) - { - throw new InvalidOperationException($"Expected signature mark, got {signature} instead !!"); - } - - byte[] buffer; - var block = new byte[BlockSizeWithPadding]; - using (var ms = new MemoryStream()) - using (var writer = new BinaryWriter(ms)) - { - while (reader.Length != reader.Position) - { - var blockSize = (int)Math.Min(reader.Length - reader.Position, BlockSizeWithPadding); - var readBytes = reader.Read(block, 0, blockSize); - if (readBytes != blockSize) - { - throw new InvalidOperationException($"Expected {blockSize} but got {readBytes} !!"); - } - - var offset = 0; - while (offset != blockSize) - { - var chunkSize = Math.Min(readBytes, ChunkSizeWithPadding); - if (!(blockSize == BlockSizeWithPadding || chunkSize == ChunkSizeWithPadding)) - { - writer.Write(block, offset, chunkSize); - } - else - { - writer.Write(block, offset, chunkSize - ChunkPadding); - } - readBytes -= chunkSize; - offset += chunkSize; - } - } - buffer = ms.ToArray(); - } - - for (int j = 0; j < buffer.Length; j++) - { - buffer[j] ^= Crypto.MarkKey[j % Crypto.MarkKey.Length]; - } - - return buffer; - } - } -} diff --git a/AssetStudio/Game/Crypto/Mr0k.cs b/AssetStudio/Game/Crypto/Mr0k.cs deleted file mode 100644 index 96e72e9..0000000 --- a/AssetStudio/Game/Crypto/Mr0k.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.IO; - -namespace AssetStudio -{ - public static class Mr0k - { - public static byte[] ExpansionKey; - public static byte[] Key; - public static byte[] ConstKey; - public static byte[] SBox; - public static byte[] BlockKey; - public static void Decrypt(ref byte[] bytes, ref int size) - { - var key1 = new byte[0x10]; - var key2 = new byte[0x10]; - var key3 = new byte[0x10]; - - Buffer.BlockCopy(bytes, 4, key1, 0, key1.Length); - Buffer.BlockCopy(bytes, 0x74, key2, 0, key2.Length); - Buffer.BlockCopy(bytes, 0x84, key3, 0, key3.Length); - - var encryptedBlockSize = Math.Min(0x10 * ((size - 0x94) >> 7), 0x400); - var encryptedBlock = new byte[encryptedBlockSize]; - - Buffer.BlockCopy(bytes, 0x94, encryptedBlock, 0, encryptedBlockSize); - - if (ConstKey != null) - { - for (int i = 0; i < ConstKey.Length; i++) - key2[i] ^= ConstKey[i]; - } - - if (SBox != null) - { - for (int i = 0; i < 0x10; i++) - key1[i] = SBox[(i % 4 * 0x100) | key1[i]]; - } - - AES.Decrypt(key1, ExpansionKey); - AES.Decrypt(key3, ExpansionKey); - - for (int i = 0; i < key1.Length; i++) - { - key1[i] ^= key3[i]; - } - - Buffer.BlockCopy(key1, 0, bytes, 0x84, key1.Length); - - var seed1 = BitConverter.ToUInt64(key2, 0); - var seed2 = BitConverter.ToUInt64(key3, 0); - var seed = seed2 ^ seed1 ^ (seed1 + (uint)size - 20); - var seedBytes = BitConverter.GetBytes(seed); - - for (var i = 0; i < encryptedBlockSize; i++) - { - encryptedBlock[i] ^= (byte)(seedBytes[i % 8] ^ Key[i]); - } - - Buffer.BlockCopy(encryptedBlock, 0, bytes, 0x94, encryptedBlockSize); - - size -= 0x14; - bytes = bytes.AsSpan(0x14, size).ToArray(); - - if (BlockKey != null) - { - for (int i = 0; i < 0xC00; i++) - { - bytes[i] ^= BlockKey[i % BlockKey.Length]; - } - - } - } - - public static bool IsMr0k(byte[] bytes) - { - using (var ms = new MemoryStream(bytes)) - using (var reader = new EndianBinaryReader(ms)) - { - var header = reader.ReadStringToNull(4); - return header == "mr0k"; - } - } - } -} diff --git a/AssetStudio/Game/GI/GIFile.cs b/AssetStudio/Game/GI/GIFile.cs deleted file mode 100644 index 4cb4926..0000000 --- a/AssetStudio/Game/GI/GIFile.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace AssetStudio -{ - public class GIFile - { - public Dictionary Bundles = new Dictionary(); - public GIFile(FileReader reader) - { - var data = Blk.Decrypt(reader); - - using (var ms = new MemoryStream(data)) - using (var subReader = new EndianBinaryReader(ms, reader.Endian)) - { - long pos = -1; - try - { - if (reader.BundlePos.Length != 0) - { - for (int i = 0; i < reader.BundlePos.Length; i++) - { - pos = reader.BundlePos[i]; - subReader.Position = pos; - var mhy0 = new Mhy0File(subReader, reader.FullPath); - Bundles.Add(pos, mhy0.FileList); - } - } - else - { - while (subReader.Position != subReader.BaseStream.Length) - { - pos = subReader.Position; - var mhy0 = new Mhy0File(subReader, reader.FullPath); - Bundles.Add(pos, mhy0.FileList); - } - } - } - catch (Exception ex) - { - Console.WriteLine($"Failed to load a mhy0 at {string.Format("0x{0:x8}", pos)} in {Path.GetFileName(reader.FullPath)}"); - Console.WriteLine(ex.Message); - } - } - } - } -} diff --git a/AssetStudio/Game/GI/Mhy0File.cs b/AssetStudio/Game/GI/Mhy0File.cs deleted file mode 100644 index dc7baf2..0000000 --- a/AssetStudio/Game/GI/Mhy0File.cs +++ /dev/null @@ -1,164 +0,0 @@ -using K4os.Compression.LZ4; -using System; -using System.IO; -using System.Linq; - -namespace AssetStudio -{ - public partial class Mhy0File - { - public class Header - { - public int Size; - public int BundleCount; - public int BlockCount; - } - - public class StorageBlock - { - public int CompressedSize; - public int UncompressedSize; - } - - public class Node - { - public long Offset; - public long Size; - public string Path; - public bool IsAssetFile; - } - - private Header m_Header; - private StorageBlock[] m_BlocksInfo; - private Node[] m_DirectoryInfo; - - public StreamFile[] FileList; - - private byte[] DecompressHeader(byte[] header) - { - using (var ms = new MemoryStream(header)) - using (var reader = new EndianBinaryReader(ms)) - { - reader.Position += 0x20; - var decompressedSize = reader.ReadMhy0Int1(); - var decompressed = new byte[decompressedSize]; - - var compressed = reader.ReadBytes((int)(reader.BaseStream.Length - reader.Position)); - - var numWrite = LZ4Codec.Decode(compressed, decompressed); - if (numWrite != decompressedSize) - throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {decompressedSize} bytes"); - - return decompressed; - } - } - - private void ReadBlocksInfoAndDirectory(byte[] header) - { - using (var ms = new MemoryStream(header)) - using (var reader = new EndianBinaryReader(ms)) - { - m_Header.BundleCount = reader.ReadMhy0Int2(); - m_DirectoryInfo = new Node[m_Header.BundleCount]; - for (int i = 0; i < m_Header.BundleCount; i++) - { - m_DirectoryInfo[i] = new Node - { - Path = reader.ReadMhy0String(), - IsAssetFile = reader.ReadMhy0Bool(), - Offset = reader.ReadMhy0Int2(), - Size = reader.ReadMhy0Int1(), - - }; - } - - m_Header.BlockCount = reader.ReadMhy0Int2(); - m_BlocksInfo = new StorageBlock[m_Header.BlockCount]; - for (int i = 0; i < m_Header.BlockCount; i++) - { - m_BlocksInfo[i] = new StorageBlock - { - CompressedSize = reader.ReadMhy0Int2(), - UncompressedSize = reader.ReadMhy0Int1() - }; - } - } - } - - private Stream CreateBlocksStream(string path) - { - Stream blocksStream; - var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.UncompressedSize); - if (uncompressedSizeSum >= int.MaxValue) - blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose); - else - blocksStream = new MemoryStream(uncompressedSizeSum); - return blocksStream; - } - - private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) - { - var compressedBytes = BigArrayPool.Shared.Rent(m_BlocksInfo.Max(x => x.CompressedSize)); - var uncompressedBytes = BigArrayPool.Shared.Rent(m_BlocksInfo.Max(x => x.UncompressedSize)); - foreach (var blockInfo in m_BlocksInfo) - { - var compressedSize = blockInfo.CompressedSize; - reader.Read(compressedBytes, 0, compressedSize); - if (compressedSize < 0x10) - throw new Exception($"Wrong compressed length: {compressedSize}"); - compressedBytes = Crypto.DescrambleEntry(compressedBytes); - var uncompressedSize = blockInfo.UncompressedSize; - var numWrite = LZ4Codec.Decode(compressedBytes.AsSpan(0xC, compressedSize - 0xC), uncompressedBytes.AsSpan(0, uncompressedSize)); - if (numWrite != uncompressedSize) - throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); - blocksStream.Write(uncompressedBytes, 0, uncompressedSize); - } - BigArrayPool.Shared.Return(compressedBytes); - BigArrayPool.Shared.Return(uncompressedBytes); - } - - private void ReadFiles(Stream blocksStream, string path) - { - FileList = new StreamFile[m_DirectoryInfo.Length]; - for (int i = 0; i < m_DirectoryInfo.Length; i++) - { - var node = m_DirectoryInfo[i]; - var file = new StreamFile(); - FileList[i] = file; - file.path = node.Path; - file.fileName = Path.GetFileName(node.Path); - if (node.Size >= int.MaxValue) - { - var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar; - Directory.CreateDirectory(extractPath); - file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); - } - else - file.stream = new MemoryStream((int)node.Size); - blocksStream.Position = node.Offset; - blocksStream.CopyTo(file.stream, node.Size); - file.stream.Position = 0; - } - } - - public Mhy0File(EndianBinaryReader reader, string path) - { - var magic = reader.ReadStringToNull(4); - if (magic != "mhy0") - throw new Exception("not a mhy0"); - - m_Header = new Header(); - m_Header.Size = reader.ReadInt32(); - var header = reader.ReadBytes(m_Header.Size); - - header = Crypto.DescrambleHeader(header); - header = DecompressHeader(header); - ReadBlocksInfoAndDirectory(header); - using (var blocksStream = CreateBlocksStream(path)) - { - ReadBlocks(reader, blocksStream); - ReadFiles(blocksStream, path); - } - } - } -} \ No newline at end of file diff --git a/AssetStudio/Game/GameFile.cs b/AssetStudio/Game/GameFile.cs deleted file mode 100644 index 25ae3f1..0000000 --- a/AssetStudio/Game/GameFile.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; - -namespace AssetStudio -{ - public class GameFile - { - public Dictionary Bundles = new Dictionary(); - - public GameFile(FileReader reader) - { - var bundles = new Dictionary(); - var ext = Path.GetExtension(reader.FileName); - switch (reader.Game.Name) - { - case "GI": - var gi = GameManager.GetGame("GI"); - if (ext != gi.Extension) - goto default; - - Blk.ExpansionKey = Crypto.GIExpansionKey; - Blk.SBox = Crypto.GISBox; - Blk.ConstKey = Crypto.GIConstKey; - Blk.ConstVal = Crypto.GIConstVal; - - var giFile = new GIFile(reader); - bundles = giFile.Bundles; - break; - case "GI_CB1": - var gi_cb1 = GameManager.GetGame("GI_CB1"); - if (ext != gi_cb1.Extension) - goto default; - - var gi_cb1File = new CB1File(reader); - bundles = gi_cb1File.Bundles; - break; - case "GI_CB2": - var gi_cb2 = GameManager.GetGame("GI_CB2"); - if (ext != gi_cb2.Extension) - goto default; - - Blk.ExpansionKey = Crypto.CBXExpansionKey; - Blk.SBox = null; - Blk.ConstKey = Crypto.CBXConstKey; - Blk.ConstVal = Crypto.CBXConstVal; - - var gi_cb2File = new CBXFile(reader); - bundles = gi_cb2File.Bundles; - break; - case "GI_CB3": - var gi_cb3 = GameManager.GetGame("GI_CB3"); - if (ext != gi_cb3.Extension) - goto default; - - Blk.ExpansionKey = Crypto.CBXExpansionKey; - Blk.SBox = null; - Blk.ConstKey = Crypto.CBXConstKey; - Blk.ConstVal = Crypto.CBXConstVal; - - var gi_cb3File = new CBXFile(reader); - bundles = gi_cb3File.Bundles; - break; - case "BH3": - var bh3 = GameManager.GetGame("BH3"); - if (ext != bh3.Extension) - goto default; - - Mr0k.ExpansionKey = Crypto.BH3ExpansionKey; - Mr0k.Key = Crypto.BH3Key; - Mr0k.ConstKey = Crypto.BH3ConstKey; - Mr0k.SBox = Crypto.BH3SBox; - Mr0k.BlockKey = null; - - var wmvFile = new WMVFile(reader); - bundles = wmvFile.Bundles; - break; - case "ZZZ_CB1": - var zzz = GameManager.GetGame("ZZZ_CB1"); - if (ext != zzz.Extension) - goto default; - - Mr0k.ExpansionKey = Crypto.Mr0kExpansionKey; - Mr0k.Key = Crypto.Mr0kKey; - Mr0k.ConstKey = Crypto.Mr0kConstKey; - Mr0k.SBox = null; - Mr0k.BlockKey = null; - - var zzzFile = new BundleFile(reader); - bundles.Add(0, zzzFile.FileList); - break; - case "SR_CB2": - var sr_cb2 = GameManager.GetGame("SR_CB2"); - if (ext != sr_cb2.Extension) - goto default; - - Mr0k.ExpansionKey = Crypto.Mr0kExpansionKey; - Mr0k.Key = Crypto.Mr0kKey; - Mr0k.ConstKey = Crypto.Mr0kConstKey; - Mr0k.SBox = null; - Mr0k.BlockKey = null; - - var sr_cb2File = new BundleFile(reader); - bundles.Add(0, sr_cb2File.FileList); - break; - case "SR_CB3": - var sr_cb3 = GameManager.GetGame("SR_CB3"); - if (ext != sr_cb3.Extension) - goto default; - - Mr0k.ExpansionKey = Crypto.Mr0kExpansionKey; - Mr0k.Key = Crypto.Mr0kKey; - Mr0k.ConstKey = Crypto.Mr0kConstKey; - Mr0k.SBox = null; - Mr0k.BlockKey = null; - - var sr_cb3File = new BlocksFile(reader); - bundles = sr_cb3File.Bundles; - break; - case "TOT": - var tot = GameManager.GetGame("TOT"); - if (ext != tot.Extension) - goto default; - - Mr0k.ExpansionKey = Crypto.Mr0kExpansionKey; - Mr0k.Key = Crypto.Mr0kKey; - Mr0k.ConstKey = Crypto.Mr0kConstKey; - Mr0k.SBox = null; - Mr0k.BlockKey = Crypto.ToTBlockKey; - - var totFile = new TOTFile(reader); - bundles = totFile.Bundles; - break; - default: - throw new NotSupportedException("File not supported !!\nMake sure to select the right game before loading the file"); - } - Bundles = bundles; - } - } -} diff --git a/AssetStudio/Game/SR_CB3/BlocksFile.cs b/AssetStudio/Game/SR_CB3/BlocksFile.cs deleted file mode 100644 index 288f537..0000000 --- a/AssetStudio/Game/SR_CB3/BlocksFile.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; - -namespace AssetStudio -{ - public class BlocksFile - { - public Dictionary Bundles = new Dictionary(); - public BlocksFile(FileReader reader) - { - if (reader.BundlePos.Length != 0) - { - foreach (var pos in reader.BundlePos) - { - reader.Position = pos; - var bundle = new BundleFile(reader); - Bundles.Add(pos, bundle.FileList); - } - } - else - { - while (reader.Position != reader.Length) - { - var pos = reader.Position; - var bundle = new BundleFile(reader); - Bundles.Add(pos, bundle.FileList); - } - } - } - } -} diff --git a/AssetStudio/Game/TOT/TOTFile.cs b/AssetStudio/Game/TOT/TOTFile.cs deleted file mode 100644 index 72b6743..0000000 --- a/AssetStudio/Game/TOT/TOTFile.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; - -namespace AssetStudio -{ - public class TOTFile - { - public Dictionary Bundles = new Dictionary(); - public TOTFile(FileReader reader) - { - if (reader.BundlePos.Length != 0) - { - foreach (var pos in reader.BundlePos) - { - reader.Position = pos; - var bundle = new BundleFile(reader); - Bundles.Add(pos, bundle.FileList); - } - } - else - { - while (reader.Position != reader.Length) - { - var pos = reader.Position; - var bundle = new BundleFile(reader); - if (bundle.FileList == null) - continue; - Bundles.Add(pos, bundle.FileList); - } - } - } - } -} diff --git a/AssetStudio/GameManager.cs b/AssetStudio/GameManager.cs index eb6cc93..2f958ba 100644 --- a/AssetStudio/GameManager.cs +++ b/AssetStudio/GameManager.cs @@ -1,7 +1,7 @@ using System; using System.Linq; -using System.Reflection; using System.Collections.Generic; +using static AssetStudio.Crypto; namespace AssetStudio { @@ -11,15 +11,22 @@ namespace AssetStudio static GameManager() { int index = 0; - Games.Add(index++, new("GI", ".blk", "GI_Data|YS_Data")); - Games.Add(index++, new("GI_CB1", ".asb", "GS_Data")); - Games.Add(index++, new("GI_CB2", ".blk", "G_Data")); - Games.Add(index++, new("GI_CB3", ".blk", "YS_Data")); - Games.Add(index++, new("BH3", ".wmv", "BH3_Data")); - Games.Add(index++, new("ZZZ_CB1", ".bundle", "Win_Data/StreamingAssets/Bundles")); - Games.Add(index++, new("SR_CB2", ".unity3d", "SR_Data")); - Games.Add(index++, new("SR_CB3", ".block", "SR_Data")); - Games.Add(index++, new("TOT", ".blk", "AssetbundlesCache")); + Games.Add(index++, new(GameType.Normal)); + Games.Add(index++, new Game(GameType.CNUnity)); + Games.Add(index++, new Mhy0(GameType.GI, GIMhy0ShiftRow, GIMhy0Key, GIMhy0Mul, GIExpansionKey, GISBox, GIInitVector, GIInitSeed)); + Games.Add(index++, new Mr0k(GameType.GI_Pack, PackExpansionKey, blockKey: PackBlockKey)); + Games.Add(index++, new Mr0k(GameType.GI_CB1)); + Games.Add(index++, new Blk(GameType.GI_CB2, GI_CBXExpansionKey, initVector: GI_CBXInitVector, initSeed: GI_CBXInitSeed)); + Games.Add(index++, new Blk(GameType.GI_CB3, GI_CBXExpansionKey, initVector: GI_CBXInitVector, initSeed: GI_CBXInitSeed)); + Games.Add(index++, new Mhy0(GameType.GI_CB3Pre, GI_CBXMhy0ShiftRow, GI_CBXMhy0Key, GI_CBXMhy0Mul, GI_CBXExpansionKey, GI_CBXSBox, GI_CBXInitVector, GI_CBXInitSeed)); + Games.Add(index++, new Mr0k(GameType.BH3, BH3ExpansionKey, BH3SBox, BH3InitVector, BH3BlockKey)); + Games.Add(index++, new Mr0k(GameType.SR_CB2, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey)); + Games.Add(index++, new Mr0k(GameType.SR_CB3, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey)); + Games.Add(index++, new Mr0k(GameType.ZZZ_CB1, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey)); + Games.Add(index++, new Mr0k(GameType.TOT, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey, postKey: ToTKey)); + Games.Add(index++, new Game(GameType.Naraka)); + Games.Add(index++, new Game(GameType.EnsembleStars)); + Games.Add(index++, new Game(GameType.OPFP)); } public static Game GetGame(int index) { @@ -31,16 +38,7 @@ namespace AssetStudio return format; } - public static Game GetGame(string name) - { - foreach(var game in Games) - { - if (game.Value.Name == name) - return game.Value; - } - - return null; - } + public static Game GetGame(string name) => Games.FirstOrDefault(x => x.Value.Name == name).Value; public static Game[] GetGames() => Games.Values.ToArray(); public static string[] GetGameNames() => Games.Values.Select(x => x.Name).ToArray(); public static string SupportedGames() => $"Supported Games:\n{string.Join("\n", Games.Values.Select(x => x.Name))}"; @@ -48,15 +46,131 @@ namespace AssetStudio public record Game { - public string Name; - public string Extension; - public string Path; - public Game(string name, string extension, string path) + public string Name { get; set; } + public GameType Type { get; } + + public Game(GameType type) { - Name = name; - Extension = extension; - Path = path; + Name = type.ToString(); + Type = type; } - public override string ToString() => Name; + + public sealed override string ToString() => Name; + } + + public record Mr0k : Game + { + public byte[] ExpansionKey { get; } + public byte[] SBox { get; } + public byte[] InitVector { get; } + public byte[] BlockKey { get; } + public byte[] PostKey { get; } + + public Mr0k(GameType type, byte[] expansionKey = null, byte[] sBox = null, byte[] initVector = null, byte[] blockKey = null, byte[] postKey = null) : base(type) + { + ExpansionKey = expansionKey ?? Array.Empty(); + SBox = sBox ?? Array.Empty(); + InitVector = initVector ?? Array.Empty(); + BlockKey = blockKey ?? Array.Empty(); + PostKey = postKey ?? Array.Empty(); + } + } + + public record Blk : Game + { + public byte[] ExpansionKey { get; } + public byte[] SBox { get; } + public byte[] InitVector { get; } + public ulong InitSeed { get; } + + public Blk(GameType type, byte[] expansionKey = null, byte[] sBox = null, byte[] initVector = null, ulong initSeed = 0) : base(type) + { + ExpansionKey = expansionKey ?? Array.Empty(); + SBox = sBox ?? Array.Empty(); + InitVector = initVector ?? Array.Empty(); + InitSeed = initSeed; + } + } + + public record Mhy0 : Blk + { + public byte[] Mhy0ShiftRow { get; } + public byte[] Mhy0Key { get; } + public byte[] Mhy0Mul { get; } + + public Mhy0(GameType type, byte[] mhy0ShiftRow, byte[] mhy0Key, byte[] mhy0Mul, byte[] expansionKey = null, byte[] sBox = null, byte[] initVector = null, ulong initSeed = 0) : base(type, expansionKey, sBox, initVector, initSeed) + { + Mhy0ShiftRow = mhy0ShiftRow; + Mhy0Key = mhy0Key; + Mhy0Mul = mhy0Mul; + } + } + + public enum GameType + { + Normal, + GI, + GI_Pack, + GI_CB1, + GI_CB2, + GI_CB3, + GI_CB3Pre, + BH3, + ZZZ_CB1, + SR_CB2, + SR_CB3, + TOT, + Naraka, + CNUnity, + EnsembleStars, + OPFP + } + + public static class GameTypes + { + public static bool IsNormal(this GameType type) => type == GameType.Normal; + public static bool IsGI(this GameType type) => type == GameType.GI; + public static bool IsGIPack(this GameType type) => type == GameType.GI_Pack; + public static bool IsGICB1(this GameType type) => type == GameType.GI_CB1; + public static bool IsGICB2(this GameType type) => type == GameType.GI_CB2; + public static bool IsGICB3(this GameType type) => type == GameType.GI_CB3; + public static bool IsGICB3Pre(this GameType type) => type == GameType.GI_CB3Pre; + public static bool IsBH3(this GameType type) => type == GameType.BH3; + public static bool IsZZZCB1(this GameType type) => type == GameType.ZZZ_CB1; + public static bool IsSRCB2(this GameType type) => type == GameType.SR_CB2; + public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3; + public static bool IsTOT(this GameType type) => type == GameType.TOT; + public static bool IsNaraka(this GameType type) => type == GameType.Naraka; + public static bool IsCNUnity(this GameType type) => type == GameType.CNUnity; + public static bool IsOPFP(this GameType type) => type == GameType.OPFP; + public static bool IsGIGroup(this GameType type) => type switch + { + GameType.GI or GameType.GI_Pack or GameType.GI_CB1 or GameType.GI_CB2 or GameType.GI_CB3 or GameType.GI_CB3Pre => true, + _ => false, + }; + + public static bool IsGISubGroup(this GameType type) => type switch + { + GameType.GI or GameType.GI_CB2 or GameType.GI_CB3 or GameType.GI_CB3Pre => true, + _ => false, + }; + + public static bool IsSRGroup(this GameType type) => type switch + { + GameType.SR_CB2 or GameType.SR_CB3 => true, + _ => false, + }; + + public static bool IsBlockFile(this GameType type) => type switch + { + GameType.BH3 or GameType.SR_CB3 or GameType.GI_Pack or GameType.TOT => true, + _ => false, + }; + + public static bool IsMhyGroup(this GameType type) => type switch + { + GameType.GI or GameType.GI_Pack or GameType.GI_CB1 or GameType.GI_CB2 or GameType.GI_CB3 or GameType.GI_CB3Pre or GameType.BH3 or GameType.SR_CB2 or GameType.SR_CB3 or GameType.TOT => true, + _ => false, + }; } } diff --git a/AssetStudio/IImported.cs b/AssetStudio/IImported.cs index 8a0448f..85b2111 100644 --- a/AssetStudio/IImported.cs +++ b/AssetStudio/IImported.cs @@ -73,23 +73,6 @@ namespace AssetStudio return null; } - public ImportedFrame FindFrame(string name) - { - if (Name == name) - { - return this; - } - foreach (var child in children) - { - var frame = child.FindFrame(name); - if (frame != null) - { - return frame; - } - } - return null; - } - public ImportedFrame FindRelativeFrameWithPath(string path) { var subs = path.Split(new[] { '/' }, 2); @@ -112,6 +95,23 @@ namespace AssetStudio return null; } + public ImportedFrame FindFrame(string name) + { + if (Name == name) + { + return this; + } + foreach (var child in children) + { + var frame = child.FindFrame(name); + if (frame != null) + { + return frame; + } + } + return null; + } + public ImportedFrame FindChild(string name, bool recursive = true) { foreach (var child in children) diff --git a/AssetStudio/ILogger.cs b/AssetStudio/ILogger.cs index 8f6c898..fe25f99 100644 --- a/AssetStudio/ILogger.cs +++ b/AssetStudio/ILogger.cs @@ -16,18 +16,21 @@ namespace AssetStudio public interface ILogger { - void Log(LoggerEvent loggerEvent, string message); + void Log(LoggerEvent loggerEvent, string message, bool silent = false); } public sealed class DummyLogger : ILogger { - public void Log(LoggerEvent loggerEvent, string message) { } + public void Log(LoggerEvent loggerEvent, string message, bool silent = false) { } } public sealed class ConsoleLogger : ILogger { - public void Log(LoggerEvent loggerEvent, string message) + public void Log(LoggerEvent loggerEvent, string message, bool silent = false) { + if (silent) + return; + Console.WriteLine("[{0}] {1}", loggerEvent, message); } } diff --git a/AssetStudio/IYAMLExportable.cs b/AssetStudio/IYAMLExportable.cs deleted file mode 100644 index 114da41..0000000 --- a/AssetStudio/IYAMLExportable.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace AssetStudio -{ - public interface IYAMLExportable - { - YAMLNode ExportYAML(); - } -} diff --git a/AssetStudio/ImportHelper.cs b/AssetStudio/ImportHelper.cs index b17e3f5..a1467b1 100644 --- a/AssetStudio/ImportHelper.cs +++ b/AssetStudio/ImportHelper.cs @@ -1,11 +1,62 @@ using Org.Brotli.Dec; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; using System.IO; using System.IO.Compression; +using System.Linq; +using static AssetStudio.BundleFile; +using static AssetStudio.Crypto; namespace AssetStudio { public static class ImportHelper { + public static void MergeSplitAssets(string path, bool allDirectories = false) + { + var splitFiles = Directory.GetFiles(path, "*.split0", allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); + foreach (var splitFile in splitFiles) + { + var destFile = Path.GetFileNameWithoutExtension(splitFile); + var destPath = Path.GetDirectoryName(splitFile); + var destFull = Path.Combine(destPath, destFile); + if (!File.Exists(destFull)) + { + var splitParts = Directory.GetFiles(destPath, destFile + ".split*"); + using (var destStream = File.Create(destFull)) + { + for (int i = 0; i < splitParts.Length; i++) + { + var splitPart = destFull + ".split" + i; + using (var sourceStream = File.OpenRead(splitPart)) + { + sourceStream.CopyTo(destStream); + } + } + } + } + } + } + + public static string[] ProcessingSplitFiles(List selectFile) + { + var splitFiles = selectFile.Where(x => x.Contains(".split")) + .Select(x => Path.Combine(Path.GetDirectoryName(x), Path.GetFileNameWithoutExtension(x))) + .Distinct() + .ToList(); + selectFile.RemoveAll(x => x.Contains(".split")); + foreach (var file in splitFiles) + { + if (File.Exists(file)) + { + selectFile.Add(file); + } + } + return selectFile.Distinct().ToArray(); + } + public static FileReader DecompressGZip(FileReader reader) { using (reader) @@ -33,5 +84,210 @@ namespace AssetStudio return new FileReader(reader.FullPath, stream); } } + + public static FileReader DecryptPack(FileReader reader, Game game) + { + const int PackSize = 0x880; + const string PackSignature = "pack"; + const string UnityFSSignature = "UnityFS"; + + var data = reader.ReadBytes((int)reader.Length); + var idx = data.Search(PackSignature); + if (idx == -1) + { + reader.Position = 0; + return reader; + } + idx = data.Search("mr0k", idx); + if (idx == -1) + { + reader.Position = 0; + return reader; + } + + var ms = new MemoryStream(); + try + { + var mr0k = (Mr0k)game; + + var bundleSize = 0; + reader.Position = 0; + Header header = null; + var pack = new { IsMr0k = false, BlockSize = -1 }; + while (reader.Remaining > 0) + { + var pos = reader.Position; + var signature = reader.ReadStringToNull(4); + if (signature == PackSignature) + { + pack = new { + IsMr0k = reader.ReadBoolean(), + BlockSize = BinaryPrimitives.ReadInt32LittleEndian(reader.ReadBytes(4)) + }; + + Span buffer = new byte[pack.BlockSize]; + reader.Read(buffer); + if (pack.IsMr0k) + { + buffer = Mr0kUtils.Decrypt(buffer, mr0k); + } + ms.Write(buffer); + + bundleSize += buffer.Length; + + if (header == null) + { + using var blockReader = new EndianBinaryReader(new MemoryStream(buffer.ToArray())); + header = new Header() + { + signature = blockReader.ReadStringToNull(), + version = blockReader.ReadUInt32(), + unityVersion = blockReader.ReadStringToNull(), + unityRevision = blockReader.ReadStringToNull(), + size = blockReader.ReadInt64() + }; + } + + if (bundleSize % (PackSize - 0x80) == 0) + { + reader.Position += PackSize - 9 - pack.BlockSize; + } + + if (bundleSize == header.size) + { + bundleSize = 0; + header = null; + pack = new { IsMr0k = false, BlockSize = -1 }; + } + + continue; + } + + reader.Position = pos; + signature = reader.ReadStringToNull(); + if (signature == UnityFSSignature) + { + header = new Header() + { + signature = reader.ReadStringToNull(), + version = reader.ReadUInt32(), + unityVersion = reader.ReadStringToNull(), + unityRevision = reader.ReadStringToNull(), + size = reader.ReadInt64() + }; + + reader.Position = pos; + reader.BaseStream.CopyTo(ms, header.size); + header = null; + continue; + } + + throw new InvalidOperationException($"Expected signature {PackSignature} or {UnityFSSignature}, got {signature} instead !!"); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(GameType.GI_Pack)} ({nameof(Mr0k)}) but got {game.Name} ({game.GetType().Name}) !!"); + } + catch (Exception e) + { + Logger.Error($"Error while reading pack file {reader.FullPath}", e); + } + finally + { + reader.Dispose(); + } + + ms.Position = 0; + return new FileReader(reader.FullPath, ms); + } + + public static FileReader DecryptMark(FileReader reader) + { + var signature = reader.ReadStringToNull(4); + if (signature != "mark") + { + reader.Position = 0; + return reader; + } + + const int BlockSize = 0xA00; + const int ChunkSize = 0x264; + const int ChunkPadding = 4; + + var blockPadding = ((BlockSize / ChunkSize) + 1) * ChunkPadding; + var chunkSizeWithPadding = ChunkSize + ChunkPadding; + var blockSizeWithPadding = BlockSize + blockPadding; + + var index = 0; + var block = new byte[blockSizeWithPadding]; + var chunk = new byte[chunkSizeWithPadding]; + var dataStream = new MemoryStream(); + while (reader.BaseStream.Length != reader.BaseStream.Position) + { + var readBlockBytes = reader.Read(block); + using var blockStream = new MemoryStream(block, 0, readBlockBytes); + while (blockStream.Length != blockStream.Position) + { + var readChunkBytes = blockStream.Read(chunk); + if (readBlockBytes == blockSizeWithPadding || readChunkBytes == chunkSizeWithPadding) + { + readChunkBytes -= ChunkPadding; + } + for (int i = 0; i < readChunkBytes; i++) + { + chunk[i] ^= MarkKey[index++ % MarkKey.Length]; + } + dataStream.Write(chunk, 0, readChunkBytes); + } + } + + reader.Dispose(); + dataStream.Position = 0; + return new FileReader(reader.FullPath, dataStream); + } + + public static FileReader DecryptEnsembleStar(FileReader reader) + { + if (Path.GetExtension(reader.FileName) == ".z") + { + return reader; + } + using (reader) + { + var data = reader.ReadBytes((int)reader.Length); + var count = data.Length; + + var stride = count % 3 + 1; + var remaining = count % 7; + var size = remaining + ~(count % 3) + EnsembleStarKey2.Length; + for (int i = 0; i < count; i += stride) + { + var offset = i / stride; + var k1 = offset % EnsembleStarKey1.Length; + var k2 = offset % EnsembleStarKey2.Length; + var k3 = offset % EnsembleStarKey3.Length; + + data[i] = (byte)(EnsembleStarKey1[k1] ^ ((size ^ EnsembleStarKey3[k3] ^ data[i] ^ EnsembleStarKey2[k2]) + remaining)); + } + + return new FileReader(reader.FullPath, new MemoryStream(data)); + } + } + + public static FileReader ParseOPFP(FileReader reader) + { + MemoryStream ms = new(); + + var data = reader.ReadBytes((int)reader.BaseStream.Length); + var idx = data.Search("UnityFS"); + if (idx != -1) + { + var count = data.Length - idx; + ms = new(data, idx, count); + } + + return new FileReader(reader.FullPath, ms); + } } } diff --git a/AssetStudio/Keys.json b/AssetStudio/Keys.json new file mode 100644 index 0000000..f82ed94 --- /dev/null +++ b/AssetStudio/Keys.json @@ -0,0 +1,38 @@ +[ + { + "Name": "PGR GLB/KR", + "Key": "kurokurokurokuro" + }, + { + "Name": "PGR CN/JP/TW", + "Key": "y5XPvqLOrCokWRIa" + }, + { + "Name": "Archeland/Kalpa of Universe", + "Key": "BlackJackProject" + }, + { + "Name": "Archeland 1.1.14", + "Key": "ProjectArcheLand" + }, + { + "Name": "Neural Cloud", + "Key": "1cab846f52901c9e" + }, + { + "Name": "Higan: Eruthyll", + "Key": "E1x2c3a4l5i6b7ur" + }, + { + "Name": "White Chord", + "Key": "yulong1868gnoluy" + }, + { + "Name": "Mecharashi", + "Key": "38C83F132E7F7A0A" + }, + { + "Name": "Castlevania: Moon Night Fantasy", + "Key": "1234567812345678" + } +] \ No newline at end of file diff --git a/AssetStudio/Logger.cs b/AssetStudio/Logger.cs index ad49398..43d737a 100644 --- a/AssetStudio/Logger.cs +++ b/AssetStudio/Logger.cs @@ -8,19 +8,20 @@ namespace AssetStudio public static class Logger { public static ILogger Default = new DummyLogger(); + public static bool Silent = false; - public static void Verbose(string message) => Default.Log(LoggerEvent.Verbose, message); - public static void Debug(string message) => Default.Log(LoggerEvent.Debug, message); - public static void Info(string message) => Default.Log(LoggerEvent.Info, message); - public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message); - public static void Error(string message) => Default.Log(LoggerEvent.Error, message); + public static void Verbose(string message) => Default.Log(LoggerEvent.Verbose, message, Silent); + public static void Debug(string message) => Default.Log(LoggerEvent.Debug, message, Silent); + public static void Info(string message) => Default.Log(LoggerEvent.Info, message, Silent); + public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message, Silent); + public static void Error(string message) => Default.Log(LoggerEvent.Error, message, Silent); public static void Error(string message, Exception e) { var sb = new StringBuilder(); sb.AppendLine(message); sb.AppendLine(e.ToString()); - Default.Log(LoggerEvent.Error, sb.ToString()); + Default.Log(LoggerEvent.Error, sb.ToString(), Silent); } } } diff --git a/AssetStudio/Math/Float.cs b/AssetStudio/Math/Float.cs deleted file mode 100644 index d022a8d..0000000 --- a/AssetStudio/Math/Float.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace AssetStudio -{ - public struct Float : IYAMLExportable - { - public float Value; - - public Float(float value) - { - Value = value; - } - - public static implicit operator Float(float value) - { - return new Float(value); - } - - public static implicit operator float(Float value) - { - return value.Value; - } - - public YAMLNode ExportYAML() - { - return new YAMLScalarNode(Value); - } - } -} diff --git a/AssetStudio/Math/Quaternion.cs b/AssetStudio/Math/Quaternion.cs index 03d7440..ca129f5 100644 --- a/AssetStudio/Math/Quaternion.cs +++ b/AssetStudio/Math/Quaternion.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace AssetStudio { [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Quaternion : IEquatable, IYAMLExportable + public struct Quaternion : IEquatable { public float X; public float Y; @@ -83,17 +83,6 @@ namespace AssetStudio return !(lhs == rhs); } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Style = MappingStyle.Flow; - node.Add("x", X); - node.Add("y", Y); - node.Add("z", Z); - node.Add("w", W); - return node; - } - private const float kEpsilon = 0.000001F; } } diff --git a/AssetStudio/Math/Vector3.cs b/AssetStudio/Math/Vector3.cs index 313fe6f..2426552 100644 --- a/AssetStudio/Math/Vector3.cs +++ b/AssetStudio/Math/Vector3.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace AssetStudio { [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Vector3 : IEquatable, IYAMLExportable + public struct Vector3 : IEquatable { public float X; public float Y; @@ -87,16 +87,6 @@ namespace AssetStudio return X * X + Y * Y + Z * Z; } - public YAMLNode ExportYAML() - { - var node = new YAMLMappingNode(); - node.Style = MappingStyle.Flow; - node.Add("x", X); - node.Add("y", Y); - node.Add("z", Z); - return node; - } - public static Vector3 Zero => new Vector3(); public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f); diff --git a/AssetStudio/Mhy0File.cs b/AssetStudio/Mhy0File.cs new file mode 100644 index 0000000..cb2cb3b --- /dev/null +++ b/AssetStudio/Mhy0File.cs @@ -0,0 +1,197 @@ +using System; +using System.IO; +using System.Linq; +using K4os.Compression.LZ4; + +namespace AssetStudio +{ + public class Mhy0File + { + private BundleFile.StorageBlock[] m_BlocksInfo; + private BundleFile.Node[] m_DirectoryInfo; + + public BundleFile.Header m_Header; + public StreamFile[] fileList; + public long Offset; + public Mhy0 mhy0; + + public Mhy0File(FileReader reader, string path, Mhy0 mhy0) + { + this.mhy0 = mhy0; + Offset = reader.Position; + reader.Endian = EndianType.LittleEndian; + + var signature = reader.ReadStringToNull(4); + m_Header = new BundleFile.Header + { + version = 6, + unityVersion = "5.x.x", + unityRevision = "2017.4.30f1", + compressedBlocksInfoSize = reader.ReadUInt32(), + flags = (ArchiveFlags)0x43 + }; + ReadBlocksInfoAndDirectory(reader); + using var blocksStream = CreateBlocksStream(path); + ReadBlocks(reader, blocksStream); + ReadFiles(blocksStream, path); + } + + private void ReadBlocksInfoAndDirectory(FileReader reader) + { + var blocksInfo = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); + DescrambleHeader(blocksInfo); + + using var blocksInfoStream = new MemoryStream(blocksInfo, 0x20, (int)m_Header.compressedBlocksInfoSize - 0x20); + using var blocksInfoReader = new EndianBinaryReader(blocksInfoStream); + m_Header.uncompressedBlocksInfoSize = blocksInfoReader.ReadMhy0UInt(); + var compressedBlocksInfo = blocksInfoReader.ReadBytes((int)blocksInfoReader.Remaining); + var uncompressedBlocksInfo = new byte[(int)m_Header.uncompressedBlocksInfoSize]; + var numWrite = LZ4Codec.Decode(compressedBlocksInfo, uncompressedBlocksInfo); + if (numWrite != m_Header.uncompressedBlocksInfoSize) + { + throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {m_Header.uncompressedBlocksInfoSize} bytes"); + } + + using var blocksInfoUncompressedStream = new MemoryStream(uncompressedBlocksInfo); + using var blocksInfoUncompressedReader = new EndianBinaryReader(blocksInfoUncompressedStream); + var nodesCount = blocksInfoUncompressedReader.ReadMhy0Int(); + m_DirectoryInfo = new BundleFile.Node[nodesCount]; + for (int i = 0; i < nodesCount; i++) + { + m_DirectoryInfo[i] = new BundleFile.Node + { + path = blocksInfoUncompressedReader.ReadMhy0String(), + flags = blocksInfoUncompressedReader.ReadBoolean() ? 4u : 0, + offset = blocksInfoUncompressedReader.ReadMhy0Int(), + size = blocksInfoUncompressedReader.ReadMhy0UInt() + }; + } + + var blocksInfoCount = blocksInfoUncompressedReader.ReadMhy0Int(); + m_BlocksInfo = new BundleFile.StorageBlock[blocksInfoCount]; + for (int i = 0; i < blocksInfoCount; i++) + { + m_BlocksInfo[i] = new BundleFile.StorageBlock + { + compressedSize = (uint)blocksInfoUncompressedReader.ReadMhy0Int(), + uncompressedSize = blocksInfoUncompressedReader.ReadMhy0UInt(), + flags = (StorageBlockFlags)0x43 + }; + } + } + + private Stream CreateBlocksStream(string path) + { + Stream blocksStream; + var uncompressedSizeSum = (int)m_BlocksInfo.Sum(x => x.uncompressedSize); + if (uncompressedSizeSum >= int.MaxValue) + blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose); + else + blocksStream = new MemoryStream(uncompressedSizeSum); + return blocksStream; + } + + private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) + { + foreach (var blockInfo in m_BlocksInfo) + { + var compressedSize = (int)blockInfo.compressedSize; + var uncompressedSize = (int)blockInfo.uncompressedSize; + if (compressedSize < 0x10) + { + throw new Exception($"Wrong compressed length: {compressedSize}"); + } + + var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); + var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize); + reader.Read(compressedBytes, 0, compressedSize); + + var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize); + var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize); + DescrambleEntry(compressedBytesSpan); + + var numWrite = LZ4Codec.Decode(compressedBytesSpan[0xC..compressedSize], uncompressedBytesSpan); + if (numWrite != uncompressedSize) + { + throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); + } + + blocksStream.Write(uncompressedBytes, 0, uncompressedSize); + BigArrayPool.Shared.Return(compressedBytes); + BigArrayPool.Shared.Return(uncompressedBytes); + } + } + + private void ReadFiles(Stream blocksStream, string path) + { + fileList = new StreamFile[m_DirectoryInfo.Length]; + for (int i = 0; i < m_DirectoryInfo.Length; i++) + { + var node = m_DirectoryInfo[i]; + var file = new StreamFile(); + fileList[i] = file; + file.path = node.path; + file.fileName = Path.GetFileName(node.path); + if (node.size >= int.MaxValue) + { + var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar; + Directory.CreateDirectory(extractPath); + file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); + } + else + file.stream = new MemoryStream((int)node.size); + blocksStream.Position = node.offset; + blocksStream.CopyTo(file.stream, node.size); + file.stream.Position = 0; + } + } + + #region Scramble + private static readonly byte[] GF256Exp = new byte[] { 0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35, 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA, 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31, 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD, 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88, 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A, 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3, 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0, 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41, 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75, 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80, 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54, 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA, 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E, 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17, 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01 }; + private static readonly byte[] GF256Log = new byte[] { 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1A, 0xC6, 0x4B, 0xC7, 0x1B, 0x68, 0x33, 0xEE, 0xDF, 0x03, 0x64, 0x04, 0xE0, 0x0E, 0x34, 0x8D, 0x81, 0xEF, 0x4C, 0x71, 0x08, 0xC8, 0xF8, 0x69, 0x1C, 0xC1, 0x7D, 0xC2, 0x1D, 0xB5, 0xF9, 0xB9, 0x27, 0x6A, 0x4D, 0xE4, 0xA6, 0x72, 0x9A, 0xC9, 0x09, 0x78, 0x65, 0x2F, 0x8A, 0x05, 0x21, 0x0F, 0xE1, 0x24, 0x12, 0xF0, 0x82, 0x45, 0x35, 0x93, 0xDA, 0x8E, 0x96, 0x8F, 0xDB, 0xBD, 0x36, 0xD0, 0xCE, 0x94, 0x13, 0x5C, 0xD2, 0xF1, 0x40, 0x46, 0x83, 0x38, 0x66, 0xDD, 0xFD, 0x30, 0xBF, 0x06, 0x8B, 0x62, 0xB3, 0x25, 0xE2, 0x98, 0x22, 0x88, 0x91, 0x10, 0x7E, 0x6E, 0x48, 0xC3, 0xA3, 0xB6, 0x1E, 0x42, 0x3A, 0x6B, 0x28, 0x54, 0xFA, 0x85, 0x3D, 0xBA, 0x2B, 0x79, 0x0A, 0x15, 0x9B, 0x9F, 0x5E, 0xCA, 0x4E, 0xD4, 0xAC, 0xE5, 0xF3, 0x73, 0xA7, 0x57, 0xAF, 0x58, 0xA8, 0x50, 0xF4, 0xEA, 0xD6, 0x74, 0x4F, 0xAE, 0xE9, 0xD5, 0xE7, 0xE6, 0xAD, 0xE8, 0x2C, 0xD7, 0x75, 0x7A, 0xEB, 0x16, 0x0B, 0xF5, 0x59, 0xCB, 0x5F, 0xB0, 0x9C, 0xA9, 0x51, 0xA0, 0x7F, 0x0C, 0xF6, 0x6F, 0x17, 0xC4, 0x49, 0xEC, 0xD8, 0x43, 0x1F, 0x2D, 0xA4, 0x76, 0x7B, 0xB7, 0xCC, 0xBB, 0x3E, 0x5A, 0xFB, 0x60, 0xB1, 0x86, 0x3B, 0x52, 0xA1, 0x6C, 0xAA, 0x55, 0x29, 0x9D, 0x97, 0xB2, 0x87, 0x90, 0x61, 0xBE, 0xDC, 0xFC, 0xBC, 0x95, 0xCF, 0xCD, 0x37, 0x3F, 0x5B, 0xD1, 0x53, 0x39, 0x84, 0x3C, 0x41, 0xA2, 0x6D, 0x47, 0x14, 0x2A, 0x9E, 0x5D, 0x56, 0xF2, 0xD3, 0xAB, 0x44, 0x11, 0x92, 0xD9, 0x23, 0x20, 0x2E, 0x89, 0xB4, 0x7C, 0xB8, 0x26, 0x77, 0x99, 0xE3, 0xA5, 0x67, 0x4A, 0xED, 0xDE, 0xC5, 0x31, 0xFE, 0x18, 0x0D, 0x63, 0x8C, 0x80, 0xC0, 0xF7, 0x70, 0x07 }; + private static int GF256Mul(int a, int b) => (a == 0 || b == 0) ? 0 : GF256Exp[(GF256Log[a] + GF256Log[b]) % 0xFF]; + + private void DescrambleChunk(Span input) + { + byte[] vector = new byte[0x10]; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 0x10; j++) + { + int k = mhy0.Mhy0ShiftRow[(2 - i) * 0x10 + j]; + int idx = j % 8; + vector[j] = (byte)(mhy0.Mhy0Key[idx] ^ mhy0.SBox[(j % 4 * 0x100) | GF256Mul(mhy0.Mhy0Mul[idx], input[k])]); + } + vector.CopyTo(input); + } + } + private void Descramble(Span input, int blockSize, int entrySize) + { + var roundedEntrySize = (entrySize + 0xF) / 0x10 * 0x10; + for (int i = 0; i < roundedEntrySize; i += 0x10) + DescrambleChunk(input.Slice(i + 4, 0x10)); + + for (int i = 0; i < 4; i++) + input[i] ^= input[i + 4]; + + var currentEntry = roundedEntrySize + 4; + var finished = false; + while (currentEntry < blockSize && !finished) + { + for (int i = 0; i < entrySize; i++) + { + input[i + currentEntry] ^= input[i + 4]; + if (i + currentEntry >= blockSize - 1) + { + finished = true; + break; + } + } + currentEntry += entrySize; + } + } + public void DescrambleHeader(Span input) => Descramble(input, 0x39, 0x1C); + public void DescrambleEntry(Span input) => Descramble(input, Math.Min(input.Length, 0x21), 8); + #endregion + } +} \ No newline at end of file diff --git a/AssetStudio/ObjectInfo.cs b/AssetStudio/ObjectInfo.cs index d637d95..1f51ab8 100644 --- a/AssetStudio/ObjectInfo.cs +++ b/AssetStudio/ObjectInfo.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text; namespace AssetStudio { @@ -17,35 +15,19 @@ namespace AssetStudio public long m_PathID; public SerializedType serializedType; - public bool HasExportableType() + public static List Filter(List objects) => objects.Where(x => x.IsExportableType()).OrderBy(x => ExportableTypes.IndexOf((ClassIDType)x.typeID)).ToList(); + + private bool IsExportableType() { var typeID = (ClassIDType)classID; var isExportableType = ExportableTypes.Contains(typeID); - switch (typeID) + return typeID switch { - case ClassIDType.IndexObject: - case ClassIDType.MiHoYoBinData: - return isExportableType && IndexObject.Exportable; - default: - return isExportableType; - } + ClassIDType.IndexObject or ClassIDType.MiHoYoBinData => isExportableType && MiHoYoBinData.Exportable, + _ => isExportableType, + }; } - public static ClassIDType[] ExportableTypes = new ClassIDType[] - { - ClassIDType.GameObject, - ClassIDType.Material, - ClassIDType.Texture2D, - ClassIDType.Mesh, - ClassIDType.Shader, - ClassIDType.TextAsset, - ClassIDType.AnimationClip, - ClassIDType.Animator, - ClassIDType.Font, - ClassIDType.AssetBundle, - ClassIDType.Sprite, - ClassIDType.MiHoYoBinData, - ClassIDType.IndexObject - }; + private readonly static List ExportableTypes = new List { ClassIDType.GameObject, ClassIDType.IndexObject, ClassIDType.Material, ClassIDType.Texture2D, ClassIDType.Mesh, ClassIDType.Shader, ClassIDType.TextAsset, ClassIDType.AnimationClip, ClassIDType.Font, ClassIDType.Sprite, ClassIDType.Animator, ClassIDType.MiHoYoBinData, ClassIDType.AssetBundle }; } } diff --git a/AssetStudio/ObjectReader.cs b/AssetStudio/ObjectReader.cs index 7105b2f..a043c4a 100644 --- a/AssetStudio/ObjectReader.cs +++ b/AssetStudio/ObjectReader.cs @@ -9,6 +9,7 @@ namespace AssetStudio public class ObjectReader : EndianBinaryReader { public SerializedFile assetsFile; + public Game Game; public long m_PathID; public long byteStart; public uint byteSize; @@ -20,10 +21,10 @@ namespace AssetStudio public int[] version => assetsFile.version; public BuildType buildType => assetsFile.buildType; - public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian) + public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo, Game game) : base(reader.BaseStream, reader.Endian) { this.assetsFile = assetsFile; - Game = reader.Game; + Game = game; m_PathID = objectInfo.m_PathID; byteStart = objectInfo.byteStart; byteSize = objectInfo.byteSize; diff --git a/AssetStudio/Progress.cs b/AssetStudio/Progress.cs index a81f108..fb142d4 100644 --- a/AssetStudio/Progress.cs +++ b/AssetStudio/Progress.cs @@ -3,19 +3,26 @@ namespace AssetStudio { public static class Progress { + public static bool Silent = false; public static IProgress Default = new Progress(); private static int preValue; public static void Reset() { - preValue = 0; - Default.Report(0); + if (!Silent) + { + preValue = 0; + Default.Report(0); + } } public static void Report(int current, int total) { - var value = (int)(current * 100f / total); - Report(value); + if (!Silent) + { + var value = (int)(current * 100f / total); + Report(value); + } } private static void Report(int value) diff --git a/AssetStudio/ResourceIndex.cs b/AssetStudio/ResourceIndex.cs index f37ac5e..8f454cc 100644 --- a/AssetStudio/ResourceIndex.cs +++ b/AssetStudio/ResourceIndex.cs @@ -82,10 +82,8 @@ namespace AssetStudio foreach (var subAsset in asset.Value) { var bundleInfo = new BundleInfo() { Bundle = asset.Key, Path = subAsset.Name }; - var blockInfo = assetIndex.Assets[asset.Key]; - ulong key = (((ulong)blockInfo.Id) << 32) | subAsset.PathHashLast; AssetLocationMap[subAsset.PathHashPre].Add(subAsset.PathHashLast, bundleInfo); - AssetMap[key] = ((ulong)subAsset.PathHashLast) << 8 | subAsset.PathHashPre; + AssetMap[subAsset.PathHashLast] = ((ulong)subAsset.PathHashLast) << 8 | subAsset.PathHashPre; } } foreach (var asset in assetIndex.Assets) @@ -112,7 +110,7 @@ namespace AssetStudio return bundleInfo; return null; } - public static string GetBundlePath(uint last) + public static string GetAssetPath(uint last) { foreach (var location in AssetLocationMap) if (location.TryGetValue(last, out var bundleInfo)) @@ -150,16 +148,6 @@ namespace AssetStudio var asset = new Asset() { Hash = hash }; return AssetLocationMap.ElementAtOrDefault(asset.Pre).ContainsKey(asset.Last); } - public static string GetContainerFromBinName(string fileName, string binName) - { - var blkName = Path.GetFileNameWithoutExtension(fileName); - var blk = Convert.ToUInt64(blkName); - var lastHex = Convert.ToUInt32(binName, 16); - var blkHash = (blk << 32) | lastHex; - var index = GetAssetIndex(blkHash); - var bundleInfo = GetBundleInfo(index); - return bundleInfo != null ? bundleInfo.Path : ""; - } } public class BundleInfo { diff --git a/AssetStudio/SerializedFile.cs b/AssetStudio/SerializedFile.cs index 8d4a2af..e3167e5 100644 --- a/AssetStudio/SerializedFile.cs +++ b/AssetStudio/SerializedFile.cs @@ -11,6 +11,8 @@ namespace AssetStudio { public AssetsManager assetsManager; public FileReader reader; + public Game game; + public long offset = 0; public string fullName; public string originalPath; public string fileName; @@ -32,11 +34,11 @@ namespace AssetStudio public List m_RefTypes; public string userInformation; - public SerializedFile(FileReader reader, AssetsManager assetsManager, string path = null) + public SerializedFile(FileReader reader, AssetsManager assetsManager) { this.assetsManager = assetsManager; this.reader = reader; - originalPath = path; + game = assetsManager.Game; fullName = reader.FullPath; fileName = reader.FileName; @@ -80,11 +82,14 @@ namespace AssetStudio if (header.m_Version >= SerializedFileFormatVersion.Unknown_8) { m_TargetPlatform = (BuildTarget)reader.ReadInt32(); - if (m_TargetPlatform == BuildTarget.NoTarget) m_TargetPlatform = BuildTarget.StandaloneWindows64; if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform)) { m_TargetPlatform = BuildTarget.UnknownPlatform; } + else if (game.Type.IsMhyGroup()) + { + m_TargetPlatform = BuildTarget.StandaloneWindows64; + } } if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes) { @@ -197,7 +202,7 @@ namespace AssetStudio m_External.guid = new Guid(reader.ReadBytes(16)); m_External.type = reader.ReadInt32(); } - m_External.pathName = reader.ReadStringToNull().Replace("cab", "CAB"); + m_External.pathName = reader.ReadStringToNull(); m_External.fileName = Path.GetFileName(m_External.pathName); m_Externals.Add(m_External); } @@ -237,7 +242,8 @@ namespace AssetStudio var type = new SerializedType(); type.classID = reader.ReadInt32(); - if (BitConverter.ToBoolean(header.m_Reserved, 0)) + + if (game.Type.IsGIGroup() && BitConverter.ToBoolean(header.m_Reserved)) { type.classID = DecodeClassID(type.classID); } @@ -348,7 +354,7 @@ namespace AssetStudio } m_Type.m_StringBuffer = reader.ReadBytes(stringBufferSize); - using (var stringBufferReader = new BinaryReader(new MemoryStream(m_Type.m_StringBuffer))) + using (var stringBufferReader = new EndianBinaryReader(new MemoryStream(m_Type.m_StringBuffer), EndianType.LittleEndian)) { for (int i = 0; i < numberOfNodes; i++) { @@ -358,7 +364,7 @@ namespace AssetStudio } } - string ReadString(BinaryReader stringBufferReader, uint value) + string ReadString(EndianBinaryReader stringBufferReader, uint value) { var isOffset = (value & 0x80000000) == 0; if (isOffset) @@ -381,12 +387,14 @@ namespace AssetStudio ObjectsDic.Add(obj.m_PathID, obj); } - private int DecodeClassID(int value) + private static int DecodeClassID(int value) { var bytes = BitConverter.GetBytes(value); - value = BinaryPrimitives.ReadInt32BigEndian(bytes); + Array.Reverse(bytes); + value = BitConverter.ToInt32(bytes, 0); return (value ^ 0x23746FBE) - 3; } + public bool IsVersionStripped => unityVersion == strippedVersion; private const string strippedVersion = "0.0.0"; diff --git a/AssetStudio/TypeTreeHelper.cs b/AssetStudio/TypeTreeHelper.cs index 7b4e959..f79df45 100644 --- a/AssetStudio/TypeTreeHelper.cs +++ b/AssetStudio/TypeTreeHelper.cs @@ -25,7 +25,7 @@ namespace AssetStudio return sb.ToString(); } - private static void ReadStringValue(StringBuilder sb, List m_Nodes, BinaryReader reader, ref int i) + private static void ReadStringValue(StringBuilder sb, List m_Nodes, EndianBinaryReader reader, ref int i) { var m_Node = m_Nodes[i]; var level = m_Node.m_Level; @@ -182,7 +182,7 @@ namespace AssetStudio return obj; } - private static object ReadValue(List m_Nodes, BinaryReader reader, ref int i) + private static object ReadValue(List m_Nodes, EndianBinaryReader reader, ref int i) { var m_Node = m_Nodes[i]; var varTypeStr = m_Node.m_Type; diff --git a/AssetStudio/UnityCNKeyManager.cs b/AssetStudio/UnityCNKeyManager.cs new file mode 100644 index 0000000..f5c6f05 --- /dev/null +++ b/AssetStudio/UnityCNKeyManager.cs @@ -0,0 +1,68 @@ +using System; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Reflection; + +namespace AssetStudio +{ + public static class CNUnityKeyManager + { + public const string KeysFileName = "Keys.json"; + + private static List Entries = new List(); + + static CNUnityKeyManager() + { + var str = File.ReadAllText(KeysFileName); + Entries = JsonConvert.DeserializeObject>(str); + } + + public static void SaveEntries(List entries) + { + Entries.Clear(); + Entries.AddRange(entries); + + var str = JsonConvert.SerializeObject(Entries); + File.WriteAllText(KeysFileName, str); + } + + public static void SetKey(int index) + { + if (TryGetEntry(index, out var cnunity)) + { + if (CNUnity.SetKey(cnunity)) + { + Logger.Info($"[CNUnity] Selected Key is {cnunity}"); + } + else + { + Logger.Info($"[CNUnity] No Key is selected !!"); + } + } + } + + public static bool TryGetEntry(int index, out CNUnity.Entry key) + { + try + { + if (index < 0 || index > Entries.Count) + { + throw new ArgumentOutOfRangeException(); + } + + key = Entries[index]; + } + catch(Exception e) + { + Logger.Error($"[CNUnity] Invalid Index, check if list is not empty !!\n{e.Message}"); + key = null; + return false; + } + + return true; + } + public static CNUnity.Entry[] GetEntries() => Entries.ToArray(); + } +} diff --git a/AssetStudio/YAML/Base/Emitter.cs b/AssetStudio/YAML/Base/Emitter.cs deleted file mode 100644 index a1604fb..0000000 --- a/AssetStudio/YAML/Base/Emitter.cs +++ /dev/null @@ -1,231 +0,0 @@ -using System; -using System.IO; -using System.Text; - -namespace AssetStudio -{ - internal class Emitter - { - public Emitter(TextWriter writer, bool formatKeys) - { - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - m_stream = writer; - IsFormatKeys = formatKeys; - if (formatKeys) - { - m_sb = new StringBuilder(); - } - } - - public Emitter IncreaseIndent() - { - m_indent++; - return this; - } - - public Emitter DecreaseIndent() - { - if (m_indent == 0) - { - throw new Exception($"Increase/decrease indent mismatch"); - } - m_indent--; - return this; - } - - public Emitter Write(char value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter WriteRaw(char value) - { - m_stream.Write(value); - return this; - } - - public Emitter Write(byte value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(ushort value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(short value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(uint value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(int value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(ulong value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(long value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(float value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(double value) - { - WriteDelayed(); - m_stream.Write(value); - return this; - } - - public Emitter Write(string value) - { - if (value.Length > 0) - { - WriteDelayed(); - m_stream.Write(value); - } - return this; - } - - public Emitter WriteFormat(string value) - { - if (value.Length > 0) - { - WriteDelayed(); - if (value.Length > 2 && value.StartsWith("m_", StringComparison.Ordinal)) - { - m_sb.Append(value, 2, value.Length - 2); - if (char.IsUpper(m_sb[0])) - { - m_sb[0] = char.ToLower(m_sb[0]); - } - value = m_sb.ToString(); - m_sb.Clear(); - } - m_stream.Write(value); - } - return this; - } - - public Emitter WriteRaw(string value) - { - m_stream.Write(value); - return this; - } - - public Emitter WriteClose(char @char) - { - m_isNeedSeparator = false; - m_isNeedWhitespace = false; - m_isNeedLineBreak = false; - return Write(@char); - } - - public Emitter WriteClose(string @string) - { - m_isNeedSeparator = false; - m_isNeedWhitespace = false; - return Write(@string); - } - - public Emitter WriteWhitespace() - { - m_isNeedWhitespace = true; - return this; - } - - public Emitter WriteSeparator() - { - m_isNeedSeparator = true; - return this; - } - - public Emitter WriteLine() - { - m_isNeedLineBreak = true; - return this; - } - - public void WriteMeta(MetaType type, string value) - { - Write('%').Write(type.ToString()).WriteWhitespace(); - Write(value).WriteLine(); - } - - public void WriteDelayed() - { - if (m_isNeedLineBreak) - { - m_stream.Write('\n'); - m_isNeedSeparator = false; - m_isNeedWhitespace = false; - m_isNeedLineBreak = false; - WriteIndent(); - } - if (m_isNeedSeparator) - { - m_stream.Write(','); - m_isNeedSeparator = false; - } - if (m_isNeedWhitespace) - { - m_stream.Write(' '); - m_isNeedWhitespace = false; - } - } - - private void WriteIndent() - { - for (int i = 0; i < m_indent * 2; i++) - { - m_stream.Write(' '); - } - } - - public bool IsFormatKeys { get; } - public bool IsKey { get; set; } - - private readonly TextWriter m_stream; - private readonly StringBuilder m_sb; - - private int m_indent = 0; - private bool m_isNeedWhitespace = false; - private bool m_isNeedSeparator = false; - private bool m_isNeedLineBreak = false; - } -} diff --git a/AssetStudio/YAML/Base/MappingStyle.cs b/AssetStudio/YAML/Base/MappingStyle.cs deleted file mode 100644 index 2c5ac25..0000000 --- a/AssetStudio/YAML/Base/MappingStyle.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace AssetStudio -{ - /// - /// Specifies the style of a mapping. - /// - public enum MappingStyle - { - /// - /// The block mapping style. - /// - Block, - - /// - /// The flow mapping style. - /// - Flow - } -} diff --git a/AssetStudio/YAML/Base/MetaType.cs b/AssetStudio/YAML/Base/MetaType.cs deleted file mode 100644 index fc6ab82..0000000 --- a/AssetStudio/YAML/Base/MetaType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace AssetStudio -{ - internal enum MetaType - { - YAML, - TAG, - } -} diff --git a/AssetStudio/YAML/Base/ScalarStyle.cs b/AssetStudio/YAML/Base/ScalarStyle.cs deleted file mode 100644 index 50e88ef..0000000 --- a/AssetStudio/YAML/Base/ScalarStyle.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace AssetStudio -{ - /// - /// Specifies the style of a YAML scalar. - /// - public enum ScalarStyle - { - /// - /// The plain scalar style. - /// - Plain, - - /// - /// - /// - Hex, - - /// - /// The single-quoted scalar style. - /// - SingleQuoted, - - /// - /// The double-quoted scalar style. - /// - DoubleQuoted, - } -} diff --git a/AssetStudio/YAML/Base/ScalarType.cs b/AssetStudio/YAML/Base/ScalarType.cs deleted file mode 100644 index a6e6cf8..0000000 --- a/AssetStudio/YAML/Base/ScalarType.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace AssetStudio -{ - internal enum ScalarType - { - Boolean, - Byte, - UInt16, - Int16, - UInt32, - Int32, - UInt64, - Int64, - Single, - Double, - String, - } -} diff --git a/AssetStudio/YAML/Base/SequenceStyle.cs b/AssetStudio/YAML/Base/SequenceStyle.cs deleted file mode 100644 index 3c61132..0000000 --- a/AssetStudio/YAML/Base/SequenceStyle.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace AssetStudio -{ - /// - /// Specifies the style of a sequence. - /// - public enum SequenceStyle - { - /// - /// The block sequence style - /// - Block, - - /// - /// The block sequence style but with curly braces - /// - BlockCurve, - - /// - /// The flow sequence style - /// - Flow, - - /// - /// Single line with hex data - /// - Raw, - } - - public static class SequenceStyleExtensions - { - public static bool IsRaw(this SequenceStyle _this) - { - return _this == SequenceStyle.Raw; - } - - public static bool IsAnyBlock(this SequenceStyle _this) - { - return _this == SequenceStyle.Block || _this == SequenceStyle.BlockCurve; - } - - /// - /// Get scalar style corresponding to current sequence style - /// - /// Sequence style - /// Corresponding scalar style - public static ScalarStyle ToScalarStyle(this SequenceStyle _this) - { - return _this == SequenceStyle.Raw ? ScalarStyle.Hex : ScalarStyle.Plain; - } - } -} diff --git a/AssetStudio/YAML/Base/YAMLDocument.cs b/AssetStudio/YAML/Base/YAMLDocument.cs deleted file mode 100644 index 1052f63..0000000 --- a/AssetStudio/YAML/Base/YAMLDocument.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace AssetStudio -{ - public sealed class YAMLDocument - { - public YAMLDocument() - { - } - - public YAMLScalarNode CreateScalarRoot() - { - YAMLScalarNode root = new YAMLScalarNode(); - Root = root; - return root; - } - - public YAMLSequenceNode CreateSequenceRoot() - { - YAMLSequenceNode root = new YAMLSequenceNode(); - Root = root; - return root; - } - - public YAMLMappingNode CreateMappingRoot() - { - YAMLMappingNode root = new YAMLMappingNode(); - Root = root; - return root; - } - - internal void Emit(Emitter emitter, bool isSeparator) - { - if(isSeparator) - { - emitter.Write("---").WriteWhitespace(); - } - - Root.Emit(emitter); - } - - public YAMLNode Root { get; private set; } - } -} diff --git a/AssetStudio/YAML/Base/YAMLMappingNode.cs b/AssetStudio/YAML/Base/YAMLMappingNode.cs deleted file mode 100644 index 75d60c1..0000000 --- a/AssetStudio/YAML/Base/YAMLMappingNode.cs +++ /dev/null @@ -1,330 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AssetStudio -{ - public sealed class YAMLMappingNode : YAMLNode - { - public YAMLMappingNode() - { - } - - public YAMLMappingNode(MappingStyle style) - { - Style = style; - } - - public void Add(int key, long value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(int key, string value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(int key, YAMLNode value) - { - YAMLScalarNode keyNode = new YAMLScalarNode(key); - InsertEnd(keyNode, value); - } - - public void Add(uint key, string value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(uint key, YAMLNode value) - { - YAMLScalarNode keyNode = new YAMLScalarNode(key); - InsertEnd(keyNode, value); - } - - public void Add(long key, string value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(long key, YAMLNode value) - { - YAMLScalarNode keyNode = new YAMLScalarNode(key); - InsertEnd(keyNode, value); - } - - public void Add(string key, bool value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, byte value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, short value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, ushort value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, int value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, uint value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, long value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, ulong value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, float value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, string value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(string key, YAMLNode value) - { - YAMLScalarNode keyNode = new YAMLScalarNode(key, true); - InsertEnd(keyNode, value); - } - - public void Add(YAMLNode key, bool value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, byte value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, short value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, ushort value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, int value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, uint value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, long value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, ulong value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, float value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, string value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - Add(key, valueNode); - } - - public void Add(YAMLNode key, YAMLNode value) - { - if (key.NodeType != YAMLNodeType.Scalar) - { - throw new Exception($"Only {YAMLNodeType.Scalar} node as a key supported"); - } - - InsertEnd(key, value); - } - - public void Append(YAMLMappingNode map) - { - foreach (KeyValuePair child in map.m_children) - { - Add(child.Key, child.Value); - } - } - - public void InsertBegin(string key, int value) - { - YAMLScalarNode valueNode = new YAMLScalarNode(value); - InsertBegin(key, valueNode); - } - - public void InsertBegin(string key, YAMLNode value) - { - YAMLScalarNode keyNode = new YAMLScalarNode(key, true); - InsertBegin(keyNode, value); - } - - public void InsertBegin(YAMLNode key, YAMLNode value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - KeyValuePair pair = new KeyValuePair(key, value); - m_children.Insert(0, pair); - } - - internal override void Emit(Emitter emitter) - { - base.Emit(emitter); - - StartChildren(emitter); - foreach (var kvp in m_children) - { - YAMLNode key = kvp.Key; - YAMLNode value = kvp.Value; - - bool iskey = emitter.IsKey; - emitter.IsKey = true; - key.Emit(emitter); - emitter.IsKey = false; - StartTransition(emitter, value); - value.Emit(emitter); - EndTransition(emitter, value); - emitter.IsKey = iskey; - } - EndChildren(emitter); - } - - private void StartChildren(Emitter emitter) - { - if (Style == MappingStyle.Block) - { - if (m_children.Count == 0) - { - emitter.Write('{'); - } - } - else if (Style == MappingStyle.Flow) - { - emitter.Write('{'); - } - } - - private void EndChildren(Emitter emitter) - { - if (Style == MappingStyle.Block) - { - if (m_children.Count == 0) - { - emitter.Write('}'); - } - emitter.WriteLine(); - } - else if (Style == MappingStyle.Flow) - { - emitter.WriteClose('}'); - } - } - - private void StartTransition(Emitter emitter, YAMLNode next) - { - emitter.Write(':').WriteWhitespace(); - if (Style == MappingStyle.Block) - { - if (next.IsMultiline) - { - emitter.WriteLine(); - } - } - if (next.IsIndent) - { - emitter.IncreaseIndent(); - } - } - - private void EndTransition(Emitter emitter, YAMLNode next) - { - if (Style == MappingStyle.Block) - { - emitter.WriteLine(); - } - else if (Style == MappingStyle.Flow) - { - emitter.WriteSeparator().WriteWhitespace(); - } - if (next.IsIndent) - { - emitter.DecreaseIndent(); - } - } - - private void InsertEnd(YAMLNode key, YAMLNode value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - KeyValuePair pair = new KeyValuePair(key, value); - m_children.Add(pair); - } - - public static YAMLMappingNode Empty { get; } = new YAMLMappingNode(MappingStyle.Flow); - - public override YAMLNodeType NodeType => YAMLNodeType.Mapping; - public override bool IsMultiline => Style == MappingStyle.Block && m_children.Count > 0; - public override bool IsIndent => Style == MappingStyle.Block; - - public MappingStyle Style { get; set; } - - private readonly List> m_children = new List>(); - } -} diff --git a/AssetStudio/YAML/Base/YAMLNode.cs b/AssetStudio/YAML/Base/YAMLNode.cs deleted file mode 100644 index f946aaa..0000000 --- a/AssetStudio/YAML/Base/YAMLNode.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace AssetStudio -{ - public abstract class YAMLNode - { - internal virtual void Emit(Emitter emitter) - { - bool isWrote = false; - if (!CustomTag.IsEmpty) - { - emitter.Write(CustomTag.ToString()).WriteWhitespace(); - isWrote = true; - } - if (Anchor.Length > 0) - { - emitter.Write("&").Write(Anchor).WriteWhitespace(); - isWrote = true; - } - - if (isWrote) - { - if (IsMultiline) - { - emitter.WriteLine(); - } - } - } - - public abstract YAMLNodeType NodeType { get; } - public abstract bool IsMultiline { get; } - public abstract bool IsIndent { get; } - - public string Tag - { - get => CustomTag.Content; - set => CustomTag = new YAMLTag(YAMLWriter.DefaultTagHandle, value); - } - public YAMLTag CustomTag { get; set; } - public string Anchor { get; set; } = string.Empty; - } -} diff --git a/AssetStudio/YAML/Base/YAMLNodeType.cs b/AssetStudio/YAML/Base/YAMLNodeType.cs deleted file mode 100644 index 04f8cdf..0000000 --- a/AssetStudio/YAML/Base/YAMLNodeType.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace AssetStudio -{ - public enum YAMLNodeType - { - /// - /// The node is a . - /// - Mapping, - - /// - /// The node is a . - /// - Scalar, - - /// - /// The node is a . - /// - Sequence - } -} diff --git a/AssetStudio/YAML/Base/YAMLScalarNode.cs b/AssetStudio/YAML/Base/YAMLScalarNode.cs deleted file mode 100644 index 7d40dce..0000000 --- a/AssetStudio/YAML/Base/YAMLScalarNode.cs +++ /dev/null @@ -1,456 +0,0 @@ -//#define USE_HEX_FLOAT - -using System; -using System.Globalization; -using System.Text.RegularExpressions; - -namespace AssetStudio -{ - public sealed class YAMLScalarNode : YAMLNode - { - public YAMLScalarNode() - { - } - - public YAMLScalarNode(bool value) : - this(value, false) - { - } - - public YAMLScalarNode(bool value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(byte value) : - this(value, false) - { - } - - public YAMLScalarNode(byte value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(short value) : - this(value, false) - { - } - - public YAMLScalarNode(short value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(ushort value) : - this(value, false) - { - } - - public YAMLScalarNode(ushort value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(int value) : - this(value, false) - { - } - - public YAMLScalarNode(int value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(uint value) : - this(value, false) - { - } - - public YAMLScalarNode(uint value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(long value) : - this(value, false) - { - } - - public YAMLScalarNode(long value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(ulong value) : - this(value, false) - { - } - - public YAMLScalarNode(ulong value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(float value) : - this(value, false) - { - } - - public YAMLScalarNode(float value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(double value) : - this(value, false) - { - } - - public YAMLScalarNode(double value, bool isHex) - { - SetValue(value); - Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain; - } - - public YAMLScalarNode(string value) - { - SetValue(value); - Style = GetStringStyle(value); - } - - internal YAMLScalarNode(string value, bool _) - { - SetValue(value); - Style = ScalarStyle.Plain; - } - - public void SetValue(bool value) - { - m_value = value ? 1u : 0u; - m_objectType = ScalarType.Boolean; - } - - public void SetValue(byte value) - { - m_value = value; - m_objectType = ScalarType.Byte; - } - - public void SetValue(short value) - { - m_value = unchecked((ushort)value); - m_objectType = ScalarType.Int16; - } - - public void SetValue(ushort value) - { - m_value = value; - m_objectType = ScalarType.UInt16; - } - - public void SetValue(int value) - { - m_value = unchecked((uint)value); - m_objectType = ScalarType.Int32; - } - - public void SetValue(uint value) - { - m_value = value; - m_objectType = ScalarType.UInt32; - } - - public void SetValue(long value) - { - m_value = unchecked((ulong)value); - m_objectType = ScalarType.Int64; - } - - public void SetValue(ulong value) - { - m_value = value; - m_objectType = ScalarType.UInt64; - } - - public void SetValue(float value) - { -#if USE_HEX_FLOAT - // It is more precise technic but output looks vague and less readable - uint hex = BitConverterExtensions.ToUInt32(value); - m_string = $"0x{hex.ToHexString()}({value.ToString(CultureInfo.InvariantCulture)})"; - m_objectType = ScalarType.String; -#else - m_value = BitConverterExtensions.ToUInt32(value); - m_objectType = ScalarType.Single; -#endif - } - - public void SetValue(double value) - { -#if USE_HEX_FLOAT - // It is more precise technic but output looks vague and less readable - ulong hex = BitConverterExtensions.ToUInt64(value); - m_string = $"0x{hex.ToHexString()}({value.ToString(CultureInfo.InvariantCulture)})"; - m_objectType = ScalarType.String; -#else - m_value = BitConverterExtensions.ToUInt64(value); - m_objectType = ScalarType.Double; -#endif - } - - public void SetValue(string value) - { - m_string = value; - m_objectType = ScalarType.String; - } - - internal Emitter ToString(Emitter emitter) - { - if (Style == ScalarStyle.Hex) - { - switch (m_objectType) - { - case ScalarType.Byte: - return emitter.WriteHex((byte)m_value); - case ScalarType.Int16: - return emitter.WriteHex(unchecked((short)m_value)); - case ScalarType.UInt16: - return emitter.WriteHex((ushort)m_value); - case ScalarType.Int32: - return emitter.WriteHex(unchecked((int)m_value)); - case ScalarType.UInt32: - return emitter.WriteHex((uint)m_value); - case ScalarType.Int64: - return emitter.WriteHex(unchecked((long)m_value)); - case ScalarType.UInt64: - return emitter.WriteHex(m_value); - case ScalarType.Single: - return emitter.WriteHex((uint)m_value); - case ScalarType.Double: - return emitter.WriteHex(m_value); - default: - throw new NotImplementedException(m_objectType.ToString()); - } - } - - switch (m_objectType) - { - case ScalarType.Boolean: - return emitter.Write(m_value); - case ScalarType.Byte: - return emitter.Write(m_value); - case ScalarType.Int16: - return emitter.Write(unchecked((short)m_value)); - case ScalarType.UInt16: - return emitter.Write(m_value); - case ScalarType.Int32: - return emitter.Write(unchecked((int)m_value)); - case ScalarType.UInt32: - return emitter.Write(m_value); - case ScalarType.Int64: - return emitter.Write(unchecked((long)m_value)); - case ScalarType.UInt64: - return emitter.Write(m_value); - case ScalarType.Single: - return emitter.Write(BitConverterExtensions.ToSingle((uint)m_value)); - case ScalarType.Double: - return emitter.Write(BitConverterExtensions.ToDouble(m_value)); - case ScalarType.String: - return WriteString(emitter); - - default: - throw new NotImplementedException(m_objectType.ToString()); - } - } - - internal override void Emit(Emitter emitter) - { - base.Emit(emitter); - - switch (Style) - { - case ScalarStyle.Hex: - case ScalarStyle.Plain: - ToString(emitter); - break; - - case ScalarStyle.SingleQuoted: - emitter.Write('\''); - ToString(emitter); - emitter.Write('\''); - break; - - case ScalarStyle.DoubleQuoted: - emitter.Write('"'); - ToString(emitter); - emitter.Write('"'); - break; - - default: - throw new Exception($"Unsupported scalar style {Style}"); - } - } - - private Emitter WriteString(Emitter emitter) - { - if (Style == ScalarStyle.Plain) - { - if (emitter.IsFormatKeys && emitter.IsKey) - { - emitter.WriteFormat(m_string); - } - else - { - emitter.Write(m_string); - } - } - else if (Style == ScalarStyle.SingleQuoted) - { - emitter.WriteDelayed(); - for (int i = 0; i < m_string.Length; i++) - { - char c = m_string[i]; - emitter.WriteRaw(c); - if (c == '\'') - { - emitter.WriteRaw(c); - } - else if (c == '\n') - { - emitter.WriteRaw("\n "); - } - } - } - else if (Style == ScalarStyle.DoubleQuoted) - { - emitter.WriteDelayed(); - for (int i = 0; i < m_string.Length; i++) - { - char c = m_string[i]; - switch (c) - { - case '\\': - emitter.WriteRaw('\\').WriteRaw('\\'); - break; - case '\n': - emitter.WriteRaw('\\').WriteRaw('n'); - break; - case '\r': - emitter.WriteRaw('\\').WriteRaw('r'); - break; - case '\t': - emitter.WriteRaw('\\').WriteRaw('t'); - break; - case '"': - emitter.WriteRaw('\\').WriteRaw('"'); - break; - - default: - emitter.WriteRaw(c); - break; - } - } - } - else - { - throw new NotSupportedException(Style.ToString()); - } - return emitter; - } - - private static ScalarStyle GetStringStyle(string value) - { - if (s_illegal.IsMatch(value)) - { - return value.Contains("\n ") ? ScalarStyle.DoubleQuoted : ScalarStyle.SingleQuoted; - } - return ScalarStyle.Plain; - } - - public static YAMLScalarNode Empty { get; } = new YAMLScalarNode(); - - public override YAMLNodeType NodeType => YAMLNodeType.Scalar; - public override bool IsMultiline => false; - public override bool IsIndent => false; - - public string Value - { - get - { - if (Style == ScalarStyle.Hex) - { - switch (m_objectType) - { - case ScalarType.Byte: - return unchecked((byte)m_value).ToHexString(); - case ScalarType.Int16: - return unchecked((short)m_value).ToHexString(); - case ScalarType.UInt16: - return unchecked((ushort)m_value).ToHexString(); - case ScalarType.Int32: - return unchecked((int)m_value).ToHexString(); - case ScalarType.UInt32: - return unchecked((uint)m_value).ToHexString(); - case ScalarType.Int64: - return unchecked((long)m_value).ToHexString(); - case ScalarType.UInt64: - return m_value.ToHexString(); - case ScalarType.Single: - return BitConverterExtensions.ToSingle((uint)m_value).ToHexString(); - case ScalarType.Double: - return BitConverterExtensions.ToDouble(m_value).ToHexString(); - default: - throw new NotImplementedException(m_objectType.ToString()); - } - } - - switch (m_objectType) - { - case ScalarType.Boolean: - return m_value == 1 ? "true" : "false"; - case ScalarType.Byte: - return m_value.ToString(); - case ScalarType.Int16: - return unchecked((short)m_value).ToString(); - case ScalarType.UInt16: - return m_value.ToString(); - case ScalarType.Int32: - return unchecked((int)m_value).ToString(); - case ScalarType.UInt32: - return m_value.ToString(); - case ScalarType.Int64: - return unchecked((long)m_value).ToString(); - case ScalarType.UInt64: - return m_value.ToString(); - case ScalarType.Single: - return BitConverterExtensions.ToSingle((uint)m_value).ToString(CultureInfo.InvariantCulture); - case ScalarType.Double: - return BitConverterExtensions.ToDouble(m_value).ToString(CultureInfo.InvariantCulture); - case ScalarType.String: - return m_string; - - default: - throw new NotImplementedException(m_objectType.ToString()); - } - } - set => m_string = value; - } - public ScalarStyle Style { get; } - - private static readonly Regex s_illegal = new Regex("(^\\s)|(^-\\s)|(^-$)|(^[\\:\\[\\]'\"*&!@#%{}?<>,\\`])|([:@]\\s)|([\\n\\r])|([:\\s]$)", RegexOptions.Compiled); - - private ScalarType m_objectType = ScalarType.String; - private string m_string = string.Empty; - private ulong m_value = 0; - } -} diff --git a/AssetStudio/YAML/Base/YAMLSequenceNode.cs b/AssetStudio/YAML/Base/YAMLSequenceNode.cs deleted file mode 100644 index 8483ee2..0000000 --- a/AssetStudio/YAML/Base/YAMLSequenceNode.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System.Collections.Generic; - -namespace AssetStudio -{ - public sealed class YAMLSequenceNode : YAMLNode - { - public YAMLSequenceNode() - { - } - - public YAMLSequenceNode(SequenceStyle style) - { - Style = style; - } - - public void Add(bool value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(byte value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(short value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(ushort value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(int value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(uint value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(long value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(ulong value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(float value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(double value) - { - YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw()); - Add(node); - } - - public void Add(string value) - { - YAMLScalarNode node = new YAMLScalarNode(value); - Add(node); - } - - public void Add(YAMLNode child) - { - m_children.Add(child); - } - - internal override void Emit(Emitter emitter) - { - base.Emit(emitter); - - StartChildren(emitter); - foreach (YAMLNode child in m_children) - { - StartChild(emitter, child); - child.Emit(emitter); - EndChild(emitter, child); - } - EndChildren(emitter); - } - - private void StartChildren(Emitter emitter) - { - switch (Style) - { - case SequenceStyle.Block: - if (m_children.Count == 0) - { - emitter.Write('['); - } - break; - - case SequenceStyle.BlockCurve: - if (m_children.Count == 0) - { - emitter.Write('{'); - } - break; - - case SequenceStyle.Flow: - emitter.Write('['); - break; - - case SequenceStyle.Raw: - if (m_children.Count == 0) - { - emitter.Write('['); - } - break; - } - } - - private void EndChildren(Emitter emitter) - { - switch (Style) - { - case SequenceStyle.Block: - if (m_children.Count == 0) - { - emitter.Write(']'); - } - emitter.WriteLine(); - break; - - case SequenceStyle.BlockCurve: - if (m_children.Count == 0) - { - emitter.WriteClose('}'); - } - emitter.WriteLine(); - break; - - case SequenceStyle.Flow: - emitter.WriteClose(']'); - break; - - case SequenceStyle.Raw: - if (m_children.Count == 0) - { - emitter.Write(']'); - } - emitter.WriteLine(); - break; - } - } - - private void StartChild(Emitter emitter, YAMLNode next) - { - if (Style.IsAnyBlock()) - { - emitter.Write('-').Write(' '); - - if (next.NodeType == NodeType) - { - emitter.IncreaseIndent(); - } - } - if (next.IsIndent) - { - emitter.IncreaseIndent(); - } - } - - private void EndChild(Emitter emitter, YAMLNode next) - { - if (Style.IsAnyBlock()) - { - emitter.WriteLine(); - if (next.NodeType == NodeType) - { - emitter.DecreaseIndent(); - } - } - else if (Style == SequenceStyle.Flow) - { - emitter.WriteSeparator().WriteWhitespace(); - } - if (next.IsIndent) - { - emitter.DecreaseIndent(); - } - } - - public static YAMLSequenceNode Empty { get; } = new YAMLSequenceNode(); - - public override YAMLNodeType NodeType => YAMLNodeType.Sequence; - public override bool IsMultiline => Style.IsAnyBlock() && m_children.Count > 0; - public override bool IsIndent => false; - - public SequenceStyle Style { get; } - - private readonly List m_children = new List(); - } -} diff --git a/AssetStudio/YAML/Base/YAMLTag.cs b/AssetStudio/YAML/Base/YAMLTag.cs deleted file mode 100644 index 073a941..0000000 --- a/AssetStudio/YAML/Base/YAMLTag.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace AssetStudio -{ - public readonly struct YAMLTag - { - public YAMLTag(string handle, string content) - { - Handle = handle; - Content = content; - } - - public override string ToString() - { - return IsEmpty ? string.Empty : $"{Handle}{Content}"; - } - - public string ToHeaderString() - { - return IsEmpty ? string.Empty : $"{Handle} {Content}"; - } - - public bool IsEmpty => string.IsNullOrEmpty(Handle); - - public string Handle { get; } - public string Content { get; } - } -} diff --git a/AssetStudio/YAML/Base/YAMLWriter.cs b/AssetStudio/YAML/Base/YAMLWriter.cs deleted file mode 100644 index 9a78e74..0000000 --- a/AssetStudio/YAML/Base/YAMLWriter.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace AssetStudio -{ - using Version = System.Version; - - public class YAMLWriter - { - public void AddDocument(YAMLDocument document) - { -#if DEBUG - if (document == null) - { - throw new ArgumentNullException(nameof(document)); - } - if (m_documents.Contains(document)) - { - throw new ArgumentException($"Document {document} is added already", nameof(document)); - } -#endif - m_documents.Add(document); - } - - public void AddTag(string handle, string content) - { - if(m_tags.Any(t => t.Handle == handle)) - { - throw new Exception($"Writer already contains tag {handle}"); - } - YAMLTag tag = new YAMLTag(handle, content); - m_tags.Add(tag); - } - - public void Write(TextWriter output) - { - WriteHead(output); - foreach (YAMLDocument doc in m_documents) - { - WriteDocument(doc); - } - WriteTail(output); - } - - public void WriteHead(TextWriter output) - { - m_emitter = new Emitter(output, IsFormatKeys); - m_isWriteSeparator = false; - - if (IsWriteVersion) - { - m_emitter.WriteMeta(MetaType.YAML, Version.ToString()); - m_isWriteSeparator = true; - } - - if (IsWriteDefaultTag) - { - m_emitter.WriteMeta(MetaType.TAG, DefaultTag.ToHeaderString()); - m_isWriteSeparator = true; - } - foreach (YAMLTag tag in m_tags) - { - m_emitter.WriteMeta(MetaType.TAG, tag.ToHeaderString()); - m_isWriteSeparator = true; - } - } - - public void WriteDocument(YAMLDocument doc) - { - doc.Emit(m_emitter, m_isWriteSeparator); - m_isWriteSeparator = true; - } - - public void WriteTail(TextWriter output) - { - output.Write('\n'); - } - - public static Version Version { get; } = new Version(1, 1); - - public const string DefaultTagHandle = "!u!"; - public const string DefaultTagContent = "tag:unity3d.com,2011:"; - - public readonly YAMLTag DefaultTag = new YAMLTag(DefaultTagHandle, DefaultTagContent); - - public bool IsWriteVersion { get; set; } = true; - public bool IsWriteDefaultTag { get; set; } = true; - public bool IsFormatKeys { get; set; } - - private readonly HashSet m_documents = new HashSet(); - private readonly List m_tags = new List(); - - private Emitter m_emitter; - private bool m_isWriteSeparator; - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/ArrayYAMLExtensions.cs b/AssetStudio/YAML/Utils/Extensions/ArrayYAMLExtensions.cs deleted file mode 100644 index bb13a30..0000000 --- a/AssetStudio/YAML/Utils/Extensions/ArrayYAMLExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Text; - -namespace AssetStudio -{ - public static class ArrayYAMLExtensions - { - public static YAMLNode ExportYAML(this byte[] _this) - { - StringBuilder sb = new StringBuilder(_this.Length * 2); - for (int i = 0; i < _this.Length; i++) - { - sb.AppendHex(_this[i]); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this T[][] _this) - where T : IYAMLExportable - { - return ((IEnumerable>)_this).ExportYAML(); - } - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/EmitterExtensions.cs b/AssetStudio/YAML/Utils/Extensions/EmitterExtensions.cs deleted file mode 100644 index 4fa0af5..0000000 --- a/AssetStudio/YAML/Utils/Extensions/EmitterExtensions.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace AssetStudio -{ - internal static class EmitterExtensions - { - public static Emitter WriteHex(this Emitter _this, byte value) - { - _this.Write(HexAlphabet[value >> 4]); - _this.Write(HexAlphabet[value & 0xF]); - return _this; - } - - public static Emitter WriteHex(this Emitter _this, ushort value) - { - _this.Write(HexAlphabet[(value >> 4) & 0xF]); - _this.Write(HexAlphabet[(value >> 0) & 0xF]); - _this.Write(HexAlphabet[(value >> 12) & 0xF]); - _this.Write(HexAlphabet[(value >> 8) & 0xF]); - return _this; - } - - public static Emitter WriteHex(this Emitter _this, short value) - { - return WriteHex(_this, unchecked((ushort)value)); - } - - public static Emitter WriteHex(this Emitter _this, uint value) - { - _this.Write(HexAlphabet[unchecked((int)(value >> 4) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 0) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 12) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 8) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 20) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 16) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 28) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 24) & 0xF)]); - return _this; - } - - public static Emitter WriteHex(this Emitter _this, int value) - { - return WriteHex(_this, unchecked((uint)value)); - } - - public static Emitter WriteHex(this Emitter _this, ulong value) - { - _this.Write(HexAlphabet[unchecked((int)(value >> 4) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 0) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 12) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 8) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 20) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 16) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 28) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 24) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 36) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 32) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 44) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 40) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 52) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 48) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 60) & 0xF)]); - _this.Write(HexAlphabet[unchecked((int)(value >> 56) & 0xF)]); - return _this; - } - - public static Emitter WriteHex(this Emitter _this, long value) - { - return WriteHex(_this, unchecked((ulong)value)); - } - - public static Emitter WriteHex(this Emitter _this, float value) - { - return WriteHex(_this, BitConverterExtensions.ToUInt32(value)); - } - - public static Emitter WriteHex(this Emitter _this, double value) - { - return WriteHex(_this, BitConverterExtensions.ToUInt64(value)); - } - - private static readonly string HexAlphabet = "0123456789ABCDEF"; - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/IDictionaryExportYAMLExtensions.cs b/AssetStudio/YAML/Utils/Extensions/IDictionaryExportYAMLExtensions.cs deleted file mode 100644 index c3d8983..0000000 --- a/AssetStudio/YAML/Utils/Extensions/IDictionaryExportYAMLExtensions.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AssetStudio -{ - public static class IDictionaryExportYAMLExtensions - { - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(kvp.Key, kvp.Value.ExportYAML()); - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(kvp.Key, kvp.Value.ExportYAML()); - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary, T2> _this) - where T1 : IYAMLExportable - where T2 : IYAMLExportable - { - // TODO: test - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode kvpMap = new YAMLMappingNode(); - YAMLMappingNode keyMap = new YAMLMappingNode(); - keyMap.Add("first", kvp.Key.Item1.ExportYAML()); - keyMap.Add("second", kvp.Key.Item2); - kvpMap.Add("first", keyMap); - kvpMap.Add("second", kvp.Value.ExportYAML()); - node.Add(kvpMap); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - YAMLNode key = kvp.Key.ExportYAML(); - if (key.NodeType == YAMLNodeType.Scalar) - { - map.Add(key, kvp.Value); - } - else - { - map.Add("first", key); - map.Add("second", kvp.Value); - } - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - YAMLNode key = kvp.Key.ExportYAML(); - if (key.NodeType == YAMLNodeType.Scalar) - { - map.Add(key, kvp.Value); - } - else - { - map.Add("first", key); - map.Add("second", kvp.Value); - } - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T1 : IYAMLExportable - where T2 : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - YAMLNode key = kvp.Key.ExportYAML(); - if (key.NodeType == YAMLNodeType.Scalar) - { - map.Add(key, kvp.Value.ExportYAML()); - } - else - { - map.Add("first", key); - map.Add("second", kvp.Value.ExportYAML()); - } - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - where T1 : IYAMLExportable - where T2 : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - YAMLNode key = kvp.Key.ExportYAML(); - if (key.NodeType == YAMLNodeType.Scalar) - { - map.Add(key, kvp.Value.ExportYAML()); - } - else - { - map.Add("first", key); - map.Add("second", kvp.Value.ExportYAML()); - } - node.Add(map); - } - return node; - } - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/IDictionaryYAMLExtensions.cs b/AssetStudio/YAML/Utils/Extensions/IDictionaryYAMLExtensions.cs deleted file mode 100644 index 6cd07b5..0000000 --- a/AssetStudio/YAML/Utils/Extensions/IDictionaryYAMLExtensions.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AssetStudio -{ - public static class IDictionaryYAMLExtensions - { - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - { - YAMLMappingNode node = new YAMLMappingNode(); - foreach (var kvp in _this) - { - node.Add(kvp.Key, kvp.Value); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - { - YAMLMappingNode node = new YAMLMappingNode(); - foreach (var kvp in _this) - { - node.Add(kvp.Key, kvp.Value); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - { - YAMLMappingNode node = new YAMLMappingNode(); - foreach (var kvp in _this) - { - node.Add(kvp.Key, kvp.Value); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - { - YAMLMappingNode node = new YAMLMappingNode(); - foreach (var kvp in _this) - { - node.Add(kvp.Key, kvp.Value); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(kvp.Key, kvp.Value); - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary, float> _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode keyNode = new YAMLMappingNode(); - keyNode.Add(kvp.Key.Item1, kvp.Key.Item2); - YAMLMappingNode kvpMap = new YAMLMappingNode(); - kvpMap.Add("first", keyNode); - kvpMap.Add("second", kvp.Value); - node.Add(kvpMap); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary, string> _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode keyNode = new YAMLMappingNode(); - keyNode.Add(kvp.Key.Item1, kvp.Key.Item2); - YAMLMappingNode kvpMap = new YAMLMappingNode(); - kvpMap.Add("first", keyNode); - kvpMap.Add("second", kvp.Value); - node.Add(kvpMap); - } - return node; - } - - public static YAMLNode ExportYAML(this IReadOnlyDictionary, string> _this, Func converter) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve); - foreach (var kvp in _this) - { - YAMLMappingNode keyNode = new YAMLMappingNode(); - keyNode.Add(converter(kvp.Key.Item1), kvp.Key.Item2); - YAMLMappingNode kvpMap = new YAMLMappingNode(); - kvpMap.Add("first", keyNode); - kvpMap.Add("second", kvp.Value); - node.Add(kvpMap); - } - return node; - } - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/IEnumerableYAMLExtensions.cs b/AssetStudio/YAML/Utils/Extensions/IEnumerableYAMLExtensions.cs deleted file mode 100644 index 26b9464..0000000 --- a/AssetStudio/YAML/Utils/Extensions/IEnumerableYAMLExtensions.cs +++ /dev/null @@ -1,273 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace AssetStudio -{ - public static class IEnumerableYAMLExtensions - { - public static YAMLNode ExportYAML(this IEnumerable _this) - { - StringBuilder sb = new StringBuilder(); - foreach (bool value in _this) - { - byte bvalue = unchecked((byte)(value ? 1 : 0)); - sb.AppendHex(bvalue); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - { - StringBuilder sb = new StringBuilder(); - foreach (char value in _this) - { - sb.AppendHex((ushort)value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - { - StringBuilder sb = new StringBuilder(); - foreach (byte value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (ushort value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (ushort value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (short value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (short value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (uint value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (uint value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (int value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (int value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (ulong value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (ulong value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(); - foreach (long value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (long value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (float value in _this) - { - node.Add(value); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (double value in _this) - { - node.Add(value); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (string value in _this) - { - node.Add(value); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable> _this) - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (IEnumerable export in _this) - { - node.Add(export.ExportYAML()); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (T export in _this) - { - node.Add(export.ExportYAML()); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable> _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (IEnumerable export in _this) - { - node.Add(export.ExportYAML()); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable> _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(kvp.Item1, kvp.Item2.ExportYAML()); - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable> _this, Func converter) - where T2 : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(converter(kvp.Item1), kvp.Item2.ExportYAML()); - node.Add(map); - } - return node; - } - - public static YAMLNode ExportYAML(this IEnumerable> _this) - where T : IYAMLExportable - { - YAMLSequenceNode node = new YAMLSequenceNode(); - foreach (var kvp in _this) - { - YAMLMappingNode map = new YAMLMappingNode(); - map.Add(kvp.Key, kvp.Value.ExportYAML()); - node.Add(map); - } - return node; - } - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/IListYAMLExtensions.cs b/AssetStudio/YAML/Utils/Extensions/IListYAMLExtensions.cs deleted file mode 100644 index 93a654f..0000000 --- a/AssetStudio/YAML/Utils/Extensions/IListYAMLExtensions.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace AssetStudio -{ - public static class IListYAMLExtensions - { - public static YAMLNode ExportYAML(this IReadOnlyList _this) - { - StringBuilder sb = new StringBuilder(_this.Count * 2); - foreach (bool value in _this) - { - byte bvalue = unchecked((byte)(value ? 1 : 0)); - sb.AppendHex(bvalue); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this) - { - StringBuilder sb = new StringBuilder(_this.Count * 4); - foreach (char value in _this) - { - sb.AppendHex((ushort)value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this) - { - StringBuilder sb = new StringBuilder(_this.Count * 2); - foreach (byte value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 4); - foreach (ushort value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (ushort value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 4); - foreach (short value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (short value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 8); - foreach (uint value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (uint value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 8); - foreach (int value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (int value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 16); - foreach (ulong value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (ulong value in _this) - { - node.Add(value); - } - return node; - } - } - - public static YAMLNode ExportYAML(this IReadOnlyList _this, bool isRaw) - { - if (isRaw) - { - StringBuilder sb = new StringBuilder(_this.Count * 16); - foreach (long value in _this) - { - sb.AppendHex(value); - } - return new YAMLScalarNode(sb.ToString(), true); - } - else - { - YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block); - foreach (long value in _this) - { - node.Add(value); - } - return node; - } - } - } -} diff --git a/AssetStudio/YAML/Utils/Extensions/YAMLMappingNodeExtensions.cs b/AssetStudio/YAML/Utils/Extensions/YAMLMappingNodeExtensions.cs deleted file mode 100644 index 034b37f..0000000 --- a/AssetStudio/YAML/Utils/Extensions/YAMLMappingNodeExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace AssetStudio -{ - public static class YAMLMappingNodeExtensions - { - public static void AddSerializedVersion(this YAMLMappingNode _this, int version) - { - if(version > 1) - { - _this.Add(SerializedVersionName, version); - } - } - - public static void ForceAddSerializedVersion(this YAMLMappingNode _this, int version) - { - if (version > 0) - { - _this.Add(SerializedVersionName, version); - } - } - - public static void InsertSerializedVersion(this YAMLMappingNode _this, int version) - { - if(version > 1) - { - _this.InsertBegin(SerializedVersionName, version); - } - } - - public const string SerializedVersionName = "serializedVersion"; - } -} diff --git a/AssetStudioCLI/App.config b/AssetStudioCLI/App.config new file mode 100644 index 0000000..7b3eab2 --- /dev/null +++ b/AssetStudioCLI/App.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AssetStudioCLI/AssetStudioCLI.csproj b/AssetStudioCLI/AssetStudioCLI.csproj index ced1645..729579a 100644 --- a/AssetStudioCLI/AssetStudioCLI.csproj +++ b/AssetStudioCLI/AssetStudioCLI.csproj @@ -1,19 +1,19 @@  - Exe - net6.0-windows + net7.0-windows Resources\as.ico - 0.18.60 - 0.18.60 - 0.18.60 - Copyright © Razmoth 2022 + 0.80.30 + 0.80.30 + 0.80.30 + Copyright © Razmoth 2022; Copyright © Perfare 2018-2022 ..\AssetStudioGUI\bin - + + @@ -22,7 +22,10 @@ - + + True + True + diff --git a/AssetStudioCLI/Exporter.cs b/AssetStudioCLI/Exporter.cs index bbcdbc2..8be0d46 100644 --- a/AssetStudioCLI/Exporter.cs +++ b/AssetStudioCLI/Exporter.cs @@ -1,9 +1,10 @@ -using System; +using AssetStudio; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using AssetStudio; -using Newtonsoft.Json; namespace AssetStudioCLI { @@ -12,18 +13,28 @@ namespace AssetStudioCLI public static bool ExportTexture2D(AssetItem item, string exportPath) { var m_Texture2D = (Texture2D)item.Asset; - var type = ImageFormat.Png; - if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath)) - return false; - var image = m_Texture2D.ConvertToImage(true); - if (image == null) - return false; - using (image) + if (Properties.Settings.Default.convertTexture) { - using (var file = File.OpenWrite(exportFullPath)) + var type = Properties.Settings.Default.convertType; + if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath)) + return false; + var image = m_Texture2D.ConvertToImage(true); + if (image == null) + return false; + using (image) { - image.WriteToStream(file, type); + using (var file = File.OpenWrite(exportFullPath)) + { + image.WriteToStream(file, type); + } + return true; } + } + else + { + if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath)) + return false; + File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData()); return true; } } @@ -35,7 +46,7 @@ namespace AssetStudioCLI if (m_AudioData == null || m_AudioData.Length == 0) return false; var converter = new AudioClipConverter(m_AudioClip); - if (converter.IsSupport) + if (Properties.Settings.Default.convertAudio && converter.IsSupport) { if (!TryExportFile(exportPath, item, ".wav", out var exportFullPath)) return false; @@ -67,9 +78,12 @@ namespace AssetStudioCLI { var m_TextAsset = (TextAsset)(item.Asset); var extension = ".txt"; - if (!string.IsNullOrEmpty(item.Container)) + if (Properties.Settings.Default.restoreExtensionName) { - extension = Path.GetExtension(item.Container); + if (!string.IsNullOrEmpty(item.Container)) + { + extension = Path.GetExtension(item.Container); + } } if (!TryExportFile(exportPath, item, extension, out var exportFullPath)) return false; @@ -85,6 +99,7 @@ namespace AssetStudioCLI switch (m_MiHoYoBinData.Type) { case MiHoYoBinDataType.JSON: + if (!TryExportFile(exportPath, item, ".json", out exportFullPath)) return false; var json = m_MiHoYoBinData.Dump() as string; @@ -95,10 +110,18 @@ namespace AssetStudioCLI } break; case MiHoYoBinDataType.Bytes: - if (!TryExportFile(exportPath, item, ".bin", out exportFullPath)) + var extension = ".bin"; + if (Properties.Settings.Default.restoreExtensionName) + { + if (!string.IsNullOrEmpty(item.Container)) + { + extension = Path.GetExtension(item.Container); + } + } + if (!TryExportFile(exportPath, item, extension, out exportFullPath)) return false; var bytes = m_MiHoYoBinData.Dump() as byte[]; - if (bytes.Length != 0) + if (!bytes.IsNullOrEmpty()) { File.WriteAllBytes(exportFullPath, bytes); return true; @@ -233,7 +256,7 @@ namespace AssetStudioCLI public static bool ExportSprite(AssetItem item, string exportPath) { - var type = ImageFormat.Png; + var type = Properties.Settings.Default.convertType; if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath)) return false; var image = ((Sprite)item.Asset).GetImage(); @@ -251,22 +274,6 @@ namespace AssetStudioCLI return false; } - public static bool ExportJsonFile(AssetItem item, string exportPath) - { - if (!TryExportFile(exportPath, item, ".json", out var exportFullPath)) - return false; - var str = JsonConvert.SerializeObject(item.Asset, Formatting.Indented); - if (!string.IsNullOrEmpty(str) && str != "{}") - { - File.WriteAllText(exportFullPath, str); - return true; - } - else - { - return ExportRawFile(item, exportPath); - } - } - public static bool ExportRawFile(AssetItem item, string exportPath) { if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath)) @@ -293,16 +300,57 @@ namespace AssetStudioCLI return false; } - public static bool ExportAnimationClip(AssetItem item, string exportPath) + public static bool ExportAnimator(AssetItem item, string exportPath, List animationList = null) { - if (!TryExportFile(exportPath, item, ".anim", out var exportFullPath)) - return false; - var m_AnimationClip = (AnimationClip)item.Asset; - var str = m_AnimationClip.Convert(Studio.Game); - File.WriteAllText(exportFullPath, str); + var exportFullPath = Path.Combine(exportPath, item.Text, item.Text + ".fbx"); + if (File.Exists(exportFullPath)) + { + exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx"); + } + var m_Animator = (Animator)item.Asset; + var convert = animationList != null + ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); + ExportFbx(convert, exportFullPath); return true; } + public static void ExportGameObject(GameObject gameObject, string exportPath, List animationList = null) + { + var convert = animationList != null + ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); + exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx"; + ExportFbx(convert, exportPath); + } + + public static void ExportGameObjectMerge(List gameObject, string exportPath, List animationList = null) + { + var rootName = Path.GetFileNameWithoutExtension(exportPath); + var convert = animationList != null + ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); + ExportFbx(convert, exportPath); + } + + private static void ExportFbx(IImported convert, string exportPath) + { + var eulerFilter = Properties.Settings.Default.eulerFilter; + var filterPrecision = (float)Properties.Settings.Default.filterPrecision; + var exportAllNodes = Properties.Settings.Default.exportAllNodes; + var exportSkins = Properties.Settings.Default.exportSkins; + var exportAnimations = Properties.Settings.Default.exportAnimations; + var exportBlendShape = Properties.Settings.Default.exportBlendShape; + var castToBone = Properties.Settings.Default.castToBone; + var boneSize = (int)Properties.Settings.Default.boneSize; + var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps; + var scaleFactor = (float)Properties.Settings.Default.scaleFactor; + var fbxVersion = Properties.Settings.Default.fbxVersion; + var fbxFormat = Properties.Settings.Default.fbxFormat; + ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, + exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1); + } + public static bool ExportDumpFile(AssetItem item, string exportPath) { if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath)) @@ -341,16 +389,28 @@ namespace AssetStudioCLI case ClassIDType.Sprite: return ExportSprite(item, exportPath); case ClassIDType.Animator: - return false; + return ExportAnimator(item, exportPath, new List()); case ClassIDType.AnimationClip: - return ExportAnimationClip(item, exportPath); + return false; case ClassIDType.MiHoYoBinData: return ExportMiHoYoBinData(item, exportPath); default: - return ExportJsonFile(item, exportPath); + return ExportRawFile(item, exportPath); } } + public static bool ExportJSONFile(AssetItem item, string exportPath) + { + if (!TryExportFile(exportPath, item, ".json", out var exportFullPath)) + return false; + + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new StringEnumConverter()); + var str = JsonConvert.SerializeObject(item.Asset, Formatting.Indented, settings); + File.WriteAllText(exportFullPath, str); + return true; + } + public static string FixFileName(string str) { if (str.Length >= 260) return Path.GetRandomFileName(); diff --git a/AssetStudioCLI/Options.cs b/AssetStudioCLI/Options.cs new file mode 100644 index 0000000..3c7d28b --- /dev/null +++ b/AssetStudioCLI/Options.cs @@ -0,0 +1,70 @@ +using System; +using AssetStudio; +using System.ComponentModel; +using System.Configuration; + +namespace AssetStudioCLI.Properties { + public static class AppSettings + { + public static string Get(string key) + { + return ConfigurationManager.AppSettings[key]; + } + + public static TValue Get(string key, TValue defaultValue) + { + try + { + var value = Get(key); + + if (string.IsNullOrEmpty(value)) + return defaultValue; + + return (TValue)TypeDescriptor.GetConverter(typeof(TValue)).ConvertFromInvariantString(value); + } + catch (Exception) + { + return defaultValue; + } + + } + } + + public class Settings + { + private static Settings defaultInstance = new Settings(); + + public static Settings Default => defaultInstance; + + public bool displayAll => AppSettings.Get("displayAll", false); + public bool enablePreview => AppSettings.Get("enablePreview", true); + public bool displayInfo => AppSettings.Get("displayInfo", true); + public bool openAfterExport => AppSettings.Get("openAfterExport", true); + public int assetGroupOption => AppSettings.Get("assetGroupOption", 0); + public bool convertTexture => AppSettings.Get("convertTexture", true); + public bool convertAudio => AppSettings.Get("convertAudio", true); + public ImageFormat convertType => AppSettings.Get("convertType", ImageFormat.Png); + public bool eulerFilter => AppSettings.Get("eulerFilter", true); + public decimal filterPrecision => AppSettings.Get("filterPrecision", (decimal)0.25); + public bool exportAllNodes => AppSettings.Get("exportAllNodes", true); + public bool exportSkins => AppSettings.Get("exportSkins", true); + public bool collectAnimations => AppSettings.Get("collectAnimations", true); + public bool exportAnimations => AppSettings.Get("exportAnimations", true); + public decimal boneSize => AppSettings.Get("boneSize", (decimal)10); + public int fbxVersion => AppSettings.Get("fbxVersion", 3); + public int fbxFormat => AppSettings.Get("fbxFormat", 0); + public decimal scaleFactor => AppSettings.Get("scaleFactor", (decimal)1); + public bool exportBlendShape => AppSettings.Get("exportBlendShape", true); + public bool castToBone => AppSettings.Get("castToBone", false); + public bool restoreExtensionName => AppSettings.Get("restoreExtensionName", true); + public bool exportAllUvsAsDiffuseMaps => AppSettings.Get("exportAllUvsAsDiffuseMaps", false); + public bool encrypted => AppSettings.Get("encrypted", true); + public byte key => AppSettings.Get("key", (byte)0x93); + public bool skipRenderer => AppSettings.Get("skipRenderer", false); + public int selectedGame => AppSettings.Get("selectedGame", 0); + public bool enableResolveDependencies => AppSettings.Get("enableResolveDependencies", true); + public int selectedCNUnityKey => AppSettings.Get("selectedCNUnityKey", 0); + public int selectedAssetMapType => AppSettings.Get("selectedAssetMapType", 0); + public bool exportMiHoYoBinData => AppSettings.Get("exportMiHoYoBinData", true); + } +} diff --git a/AssetStudioCLI/Program.cs b/AssetStudioCLI/Program.cs index a51c25c..07f29b1 100644 --- a/AssetStudioCLI/Program.cs +++ b/AssetStudioCLI/Program.cs @@ -32,9 +32,9 @@ namespace AssetStudioCLI optionsBinder.MapType, optionsBinder.MapName, optionsBinder.GroupAssetsType, - optionsBinder.NoAssetBundle, - optionsBinder.NoIndexObject, - optionsBinder.XorByte, + optionsBinder.IncludeAnimators, + optionsBinder.SkipMiHoYoBinData, + optionsBinder.Key, optionsBinder.AIFile, optionsBinder.Input, optionsBinder.Output @@ -54,36 +54,32 @@ namespace AssetStudioCLI } Studio.Game = game; + Logger.Default = new ConsoleLogger(); + assetsManager.Silent = o.Silent; assetsManager.Game = game; - AssetBundle.Exportable = !o.NoAssetBundle; - IndexObject.Exportable = !o.NoIndexObject; + MiHoYoBinData.Exportable = !o.SkipMiHoYoBinData; - if (!o.Silent) + if (o.Key != default) { - Logger.Default = new ConsoleLogger(); - } - - if (o.XorKey != default) - { - if (o.NoIndexObject) + if (o.SkipMiHoYoBinData) { - Logger.Warning("XOR key is set but IndexObject/MiHoYoBinData is excluded, ignoring key..."); + Logger.Warning("Key is set but IndexObject/MiHoYoBinData is excluded, ignoring key..."); } else { - MiHoYoBinData.doXOR = true; - MiHoYoBinData.Key = o.XorKey; + MiHoYoBinData.Encrypted = true; + MiHoYoBinData.Key = o.Key; } } - if (o.AIFile != null && game.Name == "GI" || game.Name == "GI_CB2" || game.Name == "GI_CB3") + if (o.AIFile != null && game.Type.IsGISubGroup()) { ResourceIndex.FromFile(o.AIFile.FullName); } Logger.Info("Scanning for files"); - var files = o.Input.Attributes.HasFlag(FileAttributes.Directory) ? Directory.GetFiles(o.Input.FullName, $"*{game.Extension}", SearchOption.AllDirectories).OrderBy(x => x.Length).ToArray() : new string[] { o.Input.FullName }; - Logger.Info(string.Format("Found {0} file(s)", files.Count())); + var files = o.Input.Attributes.HasFlag(FileAttributes.Directory) ? Directory.GetFiles(o.Input.FullName, "*.*", SearchOption.AllDirectories).OrderBy(x => x.Length).ToArray() : new string[] { o.Input.FullName }; + Logger.Info(string.Format("Found {0} file(s)", files.Length)); if (o.MapOp.Equals(MapOpType.None)) { @@ -91,15 +87,18 @@ namespace AssetStudioCLI foreach (var file in files) { assetsManager.LoadFiles(file); - BuildAssetData(o.TypeFilter, o.NameFilter, o.ContainerFilter, ref i); - ExportAssets(o.Output.FullName, exportableAssets, o.GroupAssetsType); + if (assetsManager.assetsFileList.Count > 0) + { + BuildAssetData(o.TypeFilter, o.NameFilter, o.ContainerFilter, ref i); + ExportAssets(o.Output.FullName, exportableAssets, o.GroupAssetsType); + } exportableAssets.Clear(); assetsManager.Clear(); } } if (o.MapOp.HasFlag(MapOpType.CABMap)) { - CABManager.BuildMap(files.ToList(), game); + AssetsHelper.BuildCABMap(files, "", "", game); } if (o.MapOp.HasFlag(MapOpType.AssetMap)) { @@ -107,16 +106,16 @@ namespace AssetStudioCLI { throw new Exception("Unable to build AssetMap with input_path as a file !!"); } - var assets = BuildAssetMap(files.ToList(), o.TypeFilter, o.NameFilter, o.ContainerFilter); + var assets = AssetsHelper.BuildAssetMap(files, game, o.TypeFilter, o.NameFilter, o.ContainerFilter); if (!o.Output.Exists) { o.Output.Create(); } if (string.IsNullOrEmpty(o.MapName)) { - o.MapName = $"assets_map_{game.Name}"; + o.MapName = "assets_map"; } - ExportAssetsMap(o.Output.FullName, assets, o.MapName, o.MapType); + AssetsHelper.ExportAssetsMap(assets, o.MapName, o.Output.FullName, o.MapType); } } catch (Exception e) @@ -141,9 +140,9 @@ namespace AssetStudioCLI public ExportListType MapType { get; set; } public string MapName { get; set; } public AssetGroupOption GroupAssetsType { get; set; } - public bool NoAssetBundle { get; set; } - public bool NoIndexObject { get; set; } - public byte XorKey { get; set; } + public bool SkipRenderer { get; set; } + public bool SkipMiHoYoBinData { get; set; } + public byte Key { get; set; } public FileInfo AIFile { get; set; } public FileInfo Input { get; set; } public DirectoryInfo Output { get; set; } @@ -160,9 +159,9 @@ namespace AssetStudioCLI public readonly Option MapType; public readonly Option MapName; public readonly Option GroupAssetsType; - public readonly Option NoAssetBundle; - public readonly Option NoIndexObject; - public readonly Option XorByte; + public readonly Option IncludeAnimators; + public readonly Option SkipMiHoYoBinData; + public readonly Option Key; public readonly Option AIFile; public readonly Argument Input; public readonly Argument Output; @@ -178,13 +177,13 @@ namespace AssetStudioCLI MapType = new Option("--map_type", "AssetMap output type."); MapName = new Option("--map_name", "Specify AssetMap file name."); GroupAssetsType = new Option("--group_assets_type", "Specify how exported assets should be grouped."); - NoAssetBundle = new Option("--no_asset_bundle", "Exclude AssetBundle from AssetMap/Export."); - NoIndexObject = new Option("--no_index_object", "Exclude IndexObject/MiHoYoBinData from AssetMap/Export."); + IncludeAnimators = new Option("--skip_re", "Include Animator with Export."); + SkipMiHoYoBinData = new Option("--skip_mihoyobindata", "Exclude IndexObject/MiHoYoBinData from AssetMap/Export."); AIFile = new Option("--ai_file", "Specify asset_index json file path (to recover GI containers).").LegalFilePathsOnly(); Input = new Argument("input_path", "Input file/folder.").LegalFilePathsOnly(); Output = new Argument("output_path", "Output folder.").LegalFilePathsOnly(); - XorByte = new Option("--xor_key", result => + Key = new Option("--key", result => { var value = result.Tokens.Single().Value; if (value.StartsWith("0x")) @@ -196,12 +195,12 @@ namespace AssetStudioCLI { return byte.Parse(value); } - }, false, "XOR key to decrypt MiHoYoBinData."); + }, false, "Key to decrypt MiHoYoBinData."); TypeFilter.AddValidator(FilterValidator); NameFilter.AddValidator(FilterValidator); ContainerFilter.AddValidator(FilterValidator); - XorByte.AddValidator(result => + Key.AddValidator(result => { var value = result.Tokens.Single().Value; try @@ -266,9 +265,9 @@ namespace AssetStudioCLI MapType = bindingContext.ParseResult.GetValueForOption(MapType), MapName = bindingContext.ParseResult.GetValueForOption(MapName), GroupAssetsType = bindingContext.ParseResult.GetValueForOption(GroupAssetsType), - NoAssetBundle = bindingContext.ParseResult.GetValueForOption(NoAssetBundle), - NoIndexObject = bindingContext.ParseResult.GetValueForOption(NoIndexObject), - XorKey = bindingContext.ParseResult.GetValueForOption(XorByte), + SkipRenderer = bindingContext.ParseResult.GetValueForOption(IncludeAnimators), + SkipMiHoYoBinData = bindingContext.ParseResult.GetValueForOption(SkipMiHoYoBinData), + Key = bindingContext.ParseResult.GetValueForOption(Key), AIFile = bindingContext.ParseResult.GetValueForOption(AIFile), Input = bindingContext.ParseResult.GetValueForArgument(Input), Output = bindingContext.ParseResult.GetValueForArgument(Output) diff --git a/AssetStudioCLI/Studio.cs b/AssetStudioCLI/Studio.cs index a3b9f7a..88be25d 100644 --- a/AssetStudioCLI/Studio.cs +++ b/AssetStudioCLI/Studio.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using static AssetStudioCLI.Exporter; using Object = AssetStudio.Object; +using System.Globalization; namespace AssetStudioCLI { @@ -20,11 +21,7 @@ namespace AssetStudioCLI CABMap, Both } - public enum ExportListType - { - XML, - JSON - } + public enum AssetGroupOption { ByType, @@ -35,7 +32,7 @@ namespace AssetStudioCLI internal static class Studio { - public static AssetsManager assetsManager = new AssetsManager() { ResolveDependancies = false }; + public static AssetsManager assetsManager = new AssetsManager() { ResolveDependencies = false }; public static List exportableAssets = new List(); public static Game Game; @@ -67,13 +64,16 @@ namespace AssetStudioCLI public static int ExtractFile(string fileName, string savePath) { int extractedCount = 0; - var reader = new FileReader(fileName, Game); + var reader = new FileReader(fileName); + reader = reader.PreProcessing(Game); if (reader.FileType == FileType.BundleFile) extractedCount += ExtractBundleFile(reader, savePath); else if (reader.FileType == FileType.WebFile) extractedCount += ExtractWebDataFile(reader, savePath); - else if (reader.FileType == FileType.GameFile) - extractedCount += ExtractGameFile(reader, savePath); + else if (reader.FileType == FileType.BlkFile) + extractedCount += ExtractBlkFile(reader, savePath); + else if (reader.FileType == FileType.BlockFile) + extractedCount += ExtractBlockFile(reader, savePath); else reader.Dispose(); return extractedCount; @@ -82,12 +82,19 @@ namespace AssetStudioCLI private static int ExtractBundleFile(FileReader reader, string savePath) { Logger.Info($"Decompressing {reader.FileName} ..."); - var bundleFile = new BundleFile(reader); - reader.Dispose(); - if (bundleFile.FileList.Length > 0) + try { - var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); - return ExtractStreamFile(extractPath, bundleFile.FileList); + var bundleFile = new BundleFile(reader, Game); + reader.Dispose(); + if (bundleFile.fileList.Length > 0) + { + var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); + return ExtractStreamFile(extractPath, bundleFile.fileList); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mr0k)} but got {Game.Name} ({Game.GetType().Name}) !!"); } return 0; } @@ -105,16 +112,69 @@ namespace AssetStudioCLI return 0; } - private static int ExtractGameFile(FileReader reader, string savePath) + private static int ExtractBlkFile(FileReader reader, string savePath) { - Logger.Info($"Decompressing {reader.FileName}..."); - var gameFile = new GameFile(reader); - reader.Dispose(); - var fileList = gameFile.Bundles.SelectMany(x => x.Value).ToList(); - if (fileList.Count > 0) + int total = 0; + Logger.Info($"Decompressing {reader.FileName} ..."); + try { - var extractPath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(reader.FileName)); - return ExtractStreamFile(extractPath, fileList.ToArray()); + using var stream = BlkUtils.Decrypt(reader, (Blk)Game); + do + { + stream.Offset = stream.RelativePosition; + var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked"); + switch (subReader.FileType) + { + case FileType.BundleFile: + total += ExtractBundleFile(subReader, subSavePath); + break; + case FileType.Mhy0File: + total += ExtractMhy0File(subReader, subSavePath); + break; + } + } while (stream.Remaining > 0); + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Blk)} but got {Game.Name} ({Game.GetType().Name}) !!"); + } + return total; + } + + private static int ExtractBlockFile(FileReader reader, string savePath) + { + int total = 0; + Logger.Info($"Decompressing {reader.FileName} ..."); + using var stream = new BlockStream(reader.BaseStream, 0); + do + { + stream.Offset = stream.RelativePosition; + var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked"); + var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + total += ExtractBundleFile(subReader, subSavePath); + } while (stream.Remaining > 0); + return total; + } + + private static int ExtractMhy0File(FileReader reader, string savePath) + { + Logger.Info($"Decompressing {reader.FileName} ..."); + try + { + var mhy0File = new Mhy0File(reader, reader.FullPath, (Mhy0)Game); + reader.Dispose(); + if (mhy0File.fileList.Length > 0) + { + var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); + return ExtractStreamFile(extractPath, mhy0File.fileList); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mhy0)} but got {Game.Name} ({Game.GetType().Name}) !!"); } return 0; } @@ -143,165 +203,29 @@ namespace AssetStudioCLI return extractedCount; } - public static List BuildAssetMap(List files, ClassIDType[] typeFilters, Regex[] nameFilters, Regex[] containerFilters) + public static void UpdateContainers() { - var assets = new List(); - for (int i = 0; i < files.Count; i++) + if (exportableAssets.Count > 0) { - var file = files[i]; - var reader = new FileReader(file, Game); - var gameFile = new GameFile(reader); - reader.Dispose(); - - foreach (var bundle in gameFile.Bundles) + Logger.Info("Updating Containers..."); + foreach (var asset in exportableAssets) { - foreach (var cab in bundle.Value) + if (int.TryParse(asset.Container, out var value)) { - var dummyPath = Path.Combine(Path.GetDirectoryName(file), cab.fileName); - using (var cabReader = new FileReader(dummyPath, cab.stream, Game)) + var last = unchecked((uint)value); + var path = ResourceIndex.GetAssetPath(last); + if (!string.IsNullOrEmpty(path)) { - if (cabReader.FileType == FileType.AssetsFile) + asset.Container = path; + if (asset.Type == ClassIDType.MiHoYoBinData) { - var assetsFile = new SerializedFile(cabReader, assetsManager, file); - assetsManager.assetsFileList.Add(assetsFile); - - assetsFile.m_Objects = assetsFile.m_Objects.Where(x => x.HasExportableType()).ToList(); - - IndexObject indexObject = null; - var containers = new List<(PPtr, string)>(assetsFile.m_Objects.Count); - var animators = new List<(PPtr, AssetEntry)>(assetsFile.m_Objects.Count); - var objectAssetItemDic = new Dictionary(assetsFile.m_Objects.Count); - foreach (var objInfo in assetsFile.m_Objects) - { - var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo); - var obj = new Object(objectReader); - var asset = new AssetEntry() - { - Source = file, - PathID = objectReader.m_PathID, - Type = objectReader.type, - Container = "" - }; - - var exportable = true; - switch (objectReader.type) - { - case ClassIDType.AssetBundle: - var assetBundle = new AssetBundle(objectReader); - foreach (var m_Container in assetBundle.Container) - { - var preloadIndex = m_Container.Value.preloadIndex; - var preloadSize = m_Container.Value.preloadSize; - var preloadEnd = preloadIndex + preloadSize; - for (int k = preloadIndex; k < preloadEnd; k++) - { - if (Game.Name == "GI" || Game.Name == "GI_CB2" || Game.Name == "GI_CB3") - { - if (long.TryParse(m_Container.Key, out var containerValue)) - { - var last = unchecked((uint)containerValue); - var path = ResourceIndex.GetBundlePath(last); - if (!string.IsNullOrEmpty(path)) - { - containers.Add((assetBundle.PreloadTable[k], path)); - continue; - } - } - } - containers.Add((assetBundle.PreloadTable[k], m_Container.Key)); - } - } - obj = null; - asset.Name = assetBundle.m_Name; - exportable = AssetBundle.Exportable; - break; - case ClassIDType.GameObject: - var gameObject = new GameObject(objectReader); - obj = gameObject; - asset.Name = gameObject.m_Name; - exportable = false; - break; - case ClassIDType.Shader: - asset.Name = objectReader.ReadAlignedString(); - if (string.IsNullOrEmpty(asset.Name)) - { - var m_parsedForm = new SerializedShader(objectReader); - asset.Name = m_parsedForm.m_Name; - } - break; - case ClassIDType.Animator: - var component = new PPtr(objectReader); - animators.Add((component, asset)); - asset.Name = "Animator"; - break; - case ClassIDType.MiHoYoBinData: - if (indexObject.Names.TryGetValue(objectReader.m_PathID, out var binName)) - { - var path = ResourceIndex.GetContainerFromBinName(file, binName); - asset.Container = path; - asset.Name = !string.IsNullOrEmpty(path) ? Path.GetFileName(path) : binName; - } - exportable = IndexObject.Exportable; - break; - case ClassIDType.IndexObject: - indexObject = new IndexObject(objectReader); - obj = null; - asset.Name = "IndexObject"; - exportable = IndexObject.Exportable; - break; - default: - asset.Name = objectReader.ReadAlignedString(); - break; - } - if (obj != null) - { - objectAssetItemDic.Add(obj, asset); - assetsFile.AddObject(obj); - } - var isMatchRegex = nameFilters.Length == 0 || nameFilters.Any(x => x.IsMatch(asset.Name) || asset.Type == ClassIDType.Animator); - var isFilteredType = typeFilters.Length == 0 || typeFilters.Contains(asset.Type) || asset.Type == ClassIDType.Animator; - if (isMatchRegex && isFilteredType && exportable) - { - assets.Add(asset); - } - } - foreach (var pair in animators) - { - if (pair.Item1.TryGet(out var gameObject) && gameObject is GameObject && (nameFilters.Length == 0 || nameFilters.Any(x => x.IsMatch(gameObject.m_Name))) && (typeFilters.Length == 0 || typeFilters.Contains(pair.Item2.Type))) - { - pair.Item2.Name = gameObject.m_Name; - } - else - { - assets.Remove(pair.Item2); - } - } - foreach ((var pptr, var container) in containers) - { - if (pptr.TryGet(out var obj)) - { - var item = objectAssetItemDic[obj]; - if (containerFilters.Length == 0 || containerFilters.Any(x => x.IsMatch(container))) - { - item.Container = container; - } - else - { - assets.Remove(item); - } - } - } - assetsManager.assetsFileList.Clear(); + asset.Text = Path.GetFileNameWithoutExtension(path); } } } } - - Logger.Info($"[{i + 1}/{files.Count}] Processed {Path.GetFileName(file)}"); - Progress.Report(i + 1, files.Count); + Logger.Info("Updated !!"); } - - return assets; } public static void BuildAssetData(ClassIDType[] typeFilters, Regex[] nameFilters, Regex[] containerFilters, ref int i) @@ -309,6 +233,7 @@ namespace AssetStudioCLI string productName = null; var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count); var objectAssetItemDic = new Dictionary(objectCount); + var mihoyoBinDataNames = new List<(PPtr, string)>(); var containers = new List<(PPtr, string)>(); foreach (var assetsFile in assetsManager.assetsFileList) { @@ -359,6 +284,7 @@ namespace AssetStudioCLI { assetItem.Text = gameObject.m_Name; } + exportable = true; break; case MonoBehaviour m_MonoBehaviour: if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script)) @@ -374,35 +300,27 @@ namespace AssetStudioCLI productName = m_PlayerSettings.productName; break; case AssetBundle m_AssetBundle: - foreach (var m_Container in m_AssetBundle.Container) + foreach (var m_Container in m_AssetBundle.m_Container) { var preloadIndex = m_Container.Value.preloadIndex; var preloadSize = m_Container.Value.preloadSize; var preloadEnd = preloadIndex + preloadSize; for (int k = preloadIndex; k < preloadEnd; k++) { - if (Game.Name == "GI" || Game.Name == "GI_CB2" || Game.Name == "GI_CB3") - { - if (long.TryParse(m_Container.Key, out var containerValue)) - { - var last = unchecked((uint)containerValue); - var path = ResourceIndex.GetBundlePath(last); - if (!string.IsNullOrEmpty(path)) - { - containers.Add((m_AssetBundle.PreloadTable[k], path)); - continue; - } - } - } - containers.Add((m_AssetBundle.PreloadTable[k], m_Container.Key)); + containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key)); } } assetItem.Text = m_AssetBundle.m_Name; - exportable = AssetBundle.Exportable; break; case IndexObject m_IndexObject: + foreach (var index in m_IndexObject.AssetMap) + { + mihoyoBinDataNames.Add((index.Value.Object, index.Key)); + } assetItem.Text = "IndexObject"; - exportable = IndexObject.Exportable; + break; + case MiHoYoBinData m_MiHoYoBinData: + exportable = MiHoYoBinData.Exportable; break; case ResourceManager m_ResourceManager: foreach (var m_Container in m_ResourceManager.m_Container) @@ -410,35 +328,6 @@ namespace AssetStudioCLI containers.Add((m_Container.Value, m_Container.Key)); } break; - case MiHoYoBinData m_MiHoYoBinData: - if (m_MiHoYoBinData.assetsFile.ObjectsDic.TryGetValue(2, out var obj) && obj is IndexObject indexObject) - { - if (indexObject.Names.TryGetValue(m_MiHoYoBinData.m_PathID, out var binName)) - { - string path = ""; - var game = GameManager.GetGame("GI"); - if (Path.GetExtension(assetsFile.originalPath) == game.Extension) - { - var blkName = Path.GetFileNameWithoutExtension(assetsFile.originalPath); - var blk = Convert.ToUInt64(blkName); - var lastHex = Convert.ToUInt32(binName, 16); - var blkHash = (blk << 32) | lastHex; - var index = ResourceIndex.GetAssetIndex(blkHash); - var bundleInfo = ResourceIndex.GetBundleInfo(index); - path = bundleInfo != null ? bundleInfo.Path : ""; - } - else - { - var last = Convert.ToUInt32(binName, 16); - path = ResourceIndex.GetBundlePath(last) ?? ""; - } - assetItem.Container = path; - assetItem.Text = !string.IsNullOrEmpty(path) ? Path.GetFileName(path) : binName; - } - } - else assetItem.Text = string.Format("BinFile #{0}", assetItem.m_PathID); - exportable = IndexObject.Exportable; - break; case NamedObject m_NamedObject: assetItem.Text = m_NamedObject.m_Name; exportable = true; @@ -457,12 +346,25 @@ namespace AssetStudioCLI } } } + foreach ((var pptr, var name) in mihoyoBinDataNames) + { + if (pptr.TryGet(out var obj)) + { + var assetItem = objectAssetItemDic[obj]; + if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash)) + { + assetItem.Text = name; + assetItem.Container = hash.ToString(); + } + else assetItem.Text = $"BinFile #{assetItem.m_PathID}"; + } + } foreach ((var pptr, var container) in containers) { if (pptr.TryGet(out var obj)) { var item = objectAssetItemDic[obj]; - if (containerFilters.Length == 0 || containerFilters.Any(x => x.IsMatch(container))) + if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container))) { item.Container = container; } @@ -472,6 +374,10 @@ namespace AssetStudioCLI } } } + if (Game.Type.IsGISubGroup()) + { + UpdateContainers(); + } containers.Clear(); } diff --git a/AssetStudioFBXNative/AssetStudioFBXNative.vcxproj b/AssetStudioFBXNative/AssetStudioFBXNative.vcxproj index 0b57773..0ffba44 100644 --- a/AssetStudioFBXNative/AssetStudioFBXNative.vcxproj +++ b/AssetStudioFBXNative/AssetStudioFBXNative.vcxproj @@ -24,7 +24,6 @@ {11ea25a3-ed68-40ee-a9d0-7fde3b583027} AssetStudioFBXNative 10.0 - AssetStudioFBXNative diff --git a/AssetStudioFBXNative/resource.h b/AssetStudioFBXNative/resource.h index 557566e..5d76072 100644 --- a/AssetStudioFBXNative/resource.h +++ b/AssetStudioFBXNative/resource.h @@ -2,7 +2,7 @@ // Microsoft Visual C++ generated include file. // Used by AssetStudioFBXNative.rc -// ¶һĬֵ +// �¶������һ��Ĭ��ֵ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS diff --git a/AssetStudioFBXWrapper/AssetStudioFBXWrapper.csproj b/AssetStudioFBXWrapper/AssetStudioFBXWrapper.csproj index c7079b7..bab3d0b 100644 --- a/AssetStudioFBXWrapper/AssetStudioFBXWrapper.csproj +++ b/AssetStudioFBXWrapper/AssetStudioFBXWrapper.csproj @@ -1,13 +1,13 @@ - net6.0 + net7.0 true - 0.18.60 - 0.18.60 - 0.18.60 + 0.80.30 + 0.80.30 + 0.80.30 Copyright © Perfare 2018-2022; Copyright © hozuki 2020 - embedded + embedded diff --git a/AssetStudioFBXWrapper/Fbx.PInvoke.cs b/AssetStudioFBXWrapper/Fbx.PInvoke.cs index 2e31b2c..8c2f36c 100644 --- a/AssetStudioFBXWrapper/Fbx.PInvoke.cs +++ b/AssetStudioFBXWrapper/Fbx.PInvoke.cs @@ -6,11 +6,11 @@ namespace AssetStudio partial class Fbx { - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz); + [LibraryImport(FbxDll.DllName)] + private static partial void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw); + [LibraryImport(FbxDll.DllName)] + private static partial void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw); } } diff --git a/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs b/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs index 91abdfa..e9ee745 100644 --- a/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs +++ b/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs @@ -1,171 +1,100 @@ -using System; -using System.Runtime.InteropServices; -using AssetStudio.PInvoke; +using System.Runtime.InteropServices; namespace AssetStudio.FbxInterop { partial class FbxExporterContext { - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxCreateContext(); + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxCreateContext(); - private static bool AsFbxInitializeContext(IntPtr context, string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps, out string errorMessage) - { - bool b; - IntPtr pErrMsg; - - using (var fileNameUtf8 = new Utf8StringHandle(fileName)) - { - b = AsFbxInitializeContext(context, fileNameUtf8.DangerousGetHandle(), scaleFactor, versionIndex, isAscii, is60Fps, out pErrMsg); - } - - errorMessage = Utf8StringHandle.ReadUtf8StringFromPointer(pErrMsg); - - return b; - } - - // Do not free the pointer strErrorMessage - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool AsFbxInitializeContext(IntPtr context, IntPtr strFileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out IntPtr strErrorMessage); + private static partial bool AsFbxInitializeContext(nint context, string fileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out string errorMessage); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxDisposeContext(ref IntPtr ppContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxDisposeContext(ref nint ppContext); - private static void AsFbxSetFramePaths(IntPtr context, string[] framePaths) + private static void AsFbxSetFramePaths(nint context, string[] framePaths) => AsFbxSetFramePaths(context, framePaths, framePaths.Length); + + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial void AsFbxSetFramePaths(nint context, string[] framePaths, int count); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxExportScene(nint context); + + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxGetSceneRootNode(nint context); + + private static nint AsFbxExportSingleFrame(nint context, nint parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale) { - var framePathCount = framePaths.Length; - - if (framePathCount == 0) - { - AsFbxSetFramePaths(context, Array.Empty(), 0); - } - else - { - var utf8Paths = new Utf8StringHandle[framePathCount]; - - try - { - for (var i = 0; i < framePathCount; i += 1) - { - utf8Paths[i] = new Utf8StringHandle(framePaths[i]); - } - - var pathPointers = new IntPtr[framePathCount]; - - for (var i = 0; i < framePathCount; i += 1) - { - pathPointers[i] = utf8Paths[i].DangerousGetHandle(); - } - - AsFbxSetFramePaths(context, pathPointers, framePathCount); - } - finally - { - foreach (var path in utf8Paths) - { - path?.Dispose(); - } - } - } + return AsFbxExportSingleFrame(context, parentNode, framePath, frameName, localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z); } - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxSetFramePaths(IntPtr context, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] strFramePaths, int count); + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial nint AsFbxExportSingleFrame(nint context, nint parentNode, string strFramePath, string strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxExportScene(IntPtr context); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxSetJointsNode_CastToBone(nint context, nint node, float boneSize); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxGetSceneRootNode(IntPtr context); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxSetJointsNode_BoneInPath(nint context, nint node, float boneSize); - private static IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale) + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxSetJointsNode_Generic(nint context, nint node); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxPrepareMaterials(nint context, int materialCount, int textureCount); + + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial nint AsFbxCreateTexture(nint context, string matTexName); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxLinkTexture(int dest, nint texture, nint material, float offsetX, float offsetY, float scaleX, float scaleY); + + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxMeshCreateClusterArray(int boneCount); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshDisposeClusterArray(ref nint ppArray); + + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxMeshCreateCluster(nint context, nint boneNode); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshAddCluster(nint array, nint cluster); + + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxMeshCreateMesh(nint context, nint frameNode); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshInitControlPoints(nint mesh, int vertexCount); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateElementNormal(nint mesh); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateDiffuseUV(nint mesh, int uv); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateNormalMapUV(nint mesh, int uv); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateElementTangent(nint mesh); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateElementVertexColor(nint mesh); + + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshCreateElementMaterial(nint mesh); + + private static nint AsFbxCreateMaterial(nint pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency) { - using (var framePathUtf8 = new Utf8StringHandle(framePath)) - { - using (var frameNameUtf8 = new Utf8StringHandle(frameName)) - { - return AsFbxExportSingleFrame(context, parentNode, framePathUtf8.DangerousGetHandle(), frameNameUtf8.DangerousGetHandle(), localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z); - } - } + return AsFbxCreateMaterial(pContext, matName, diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency); } - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, IntPtr strFramePath, IntPtr strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxSetJointsNode_CastToBone(IntPtr context, IntPtr node, float boneSize); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxSetJointsNode_BoneInPath(IntPtr context, IntPtr node, float boneSize); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxSetJointsNode_Generic(IntPtr context, IntPtr node); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxPrepareMaterials(IntPtr context, int materialCount, int textureCount); - - private static IntPtr AsFbxCreateTexture(IntPtr context, string matTexName) - { - using (var matTexNameUtf8 = new Utf8StringHandle(matTexName)) - { - return AsFbxCreateTexture(context, matTexNameUtf8.DangerousGetHandle()); - } - } - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxCreateTexture(IntPtr context, IntPtr strMatTexName); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxLinkTexture(int dest, IntPtr texture, IntPtr material, float offsetX, float offsetY, float scaleX, float scaleY); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxMeshCreateClusterArray(int boneCount); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshDisposeClusterArray(ref IntPtr ppArray); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxMeshCreateCluster(IntPtr context, IntPtr boneNode); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshAddCluster(IntPtr array, IntPtr cluster); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxMeshCreateMesh(IntPtr context, IntPtr frameNode); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshInitControlPoints(IntPtr mesh, int vertexCount); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateElementNormal(IntPtr mesh); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateDiffuseUV(IntPtr mesh, int uv); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateNormalMapUV(IntPtr mesh, int uv); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateElementTangent(IntPtr mesh); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateElementVertexColor(IntPtr mesh); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshCreateElementMaterial(IntPtr mesh); - - private static IntPtr AsFbxCreateMaterial(IntPtr pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency) - { - using (var matNameUtf8 = new Utf8StringHandle(matName)) - { - return AsFbxCreateMaterial(pContext, matNameUtf8.DangerousGetHandle(), diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency); - } - } - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxCreateMaterial(IntPtr pContext, IntPtr pMatName, + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial nint AsFbxCreateMaterial(nint pContext, string pMatName, float diffuseR, float diffuseG, float diffuseB, float ambientR, float ambientG, float ambientB, float emissiveR, float emissiveG, float emissiveB, @@ -173,153 +102,121 @@ namespace AssetStudio.FbxInterop float reflectR, float reflectG, float reflectB, float shininess, float transparency); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern int AsFbxAddMaterialToFrame(IntPtr frameNode, IntPtr material); + [LibraryImport(FbxDll.DllName)] + private static partial int AsFbxAddMaterialToFrame(nint frameNode, nint material); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxSetFrameShadingModeToTextureShading(IntPtr frameNode); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxSetFrameShadingModeToTextureShading(nint frameNode); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshSetControlPoint(IntPtr mesh, int index, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshSetControlPoint(nint mesh, int index, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshAddPolygon(IntPtr mesh, int materialIndex, int index0, int index1, int index2); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshAddPolygon(nint mesh, int materialIndex, int index0, int index1, int index2); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshElementNormalAdd(IntPtr mesh, int elementIndex, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshElementNormalAdd(nint mesh, int elementIndex, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshElementUVAdd(IntPtr mesh, int elementIndex, float u, float v); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshElementUVAdd(nint mesh, int elementIndex, float u, float v); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshElementTangentAdd(IntPtr mesh, int elementIndex, float x, float y, float z, float w); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshElementTangentAdd(nint mesh, int elementIndex, float x, float y, float z, float w); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshElementVertexColorAdd(IntPtr mesh, int elementIndex, float r, float g, float b, float a); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshElementVertexColorAdd(nint mesh, int elementIndex, float r, float g, float b, float a); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshSetBoneWeight(IntPtr pClusterArray, int boneIndex, int vertexIndex, float weight); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshSetBoneWeight(nint pClusterArray, int boneIndex, int vertexIndex, float weight); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxMeshCreateSkinContext(IntPtr context, IntPtr frameNode); + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxMeshCreateSkinContext(nint context, nint frameNode); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshDisposeSkinContext(ref IntPtr ppSkinContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshDisposeSkinContext(ref nint ppSkinContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] + [LibraryImport(FbxDll.DllName)] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool FbxClusterArray_HasItemAt(IntPtr pClusterArray, int index); + private static partial bool FbxClusterArray_HasItemAt(nint pClusterArray, int index); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private unsafe static extern void AsFbxMeshSkinAddCluster(IntPtr pSkinContext, IntPtr pClusterArray, int index, float* pBoneMatrix); + [LibraryImport(FbxDll.DllName)] + private static unsafe partial void AsFbxMeshSkinAddCluster(nint pSkinContext, nint pClusterArray, int index, float* pBoneMatrix); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMeshAddDeformer(IntPtr pSkinContext, IntPtr pMesh); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMeshAddDeformer(nint pSkinContext, nint pMesh); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter); + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimDisposeContext(ref IntPtr ppAnimContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimDisposeContext(ref nint ppAnimContext); - private static void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, string takeName) - { - using (var takeNameUtf8 = new Utf8StringHandle(takeName)) - { - AsFbxAnimPrepareStackAndLayer(pContext, pAnimContext, takeNameUtf8.DangerousGetHandle()); - } - } + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial void AsFbxAnimPrepareStackAndLayer(nint pContext, nint pAnimContext, string takeName); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, IntPtr strTakeName); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimLoadCurves(nint pNode, nint pAnimContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimLoadCurves(IntPtr pNode, IntPtr pAnimContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimBeginKeyModify(nint pAnimContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimBeginKeyModify(IntPtr pAnimContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimEndKeyModify(nint pAnimContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimEndKeyModify(IntPtr pAnimContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimAddScalingKey(nint pAnimContext, float time, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimAddScalingKey(IntPtr pAnimContext, float time, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimAddRotationKey(nint pAnimContext, float time, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimAddRotationKey(IntPtr pAnimContext, float time, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimAddTranslationKey(nint pAnimContext, float time, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimAddTranslationKey(IntPtr pAnimContext, float time, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimApplyEulerFilter(nint pAnimContext, float filterPrecision); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimApplyEulerFilter(IntPtr pAnimContext, float filterPrecision); + [LibraryImport(FbxDll.DllName)] + private static partial int AsFbxAnimGetCurrentBlendShapeChannelCount(nint pAnimContext, nint pNode); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern int AsFbxAnimGetCurrentBlendShapeChannelCount(IntPtr pAnimContext, IntPtr pNode); - - private static bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, string channelName) - { - using (var channelNameUtf8 = new Utf8StringHandle(channelName)) - { - return AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, channelNameUtf8.DangerousGetHandle()); - } - } - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, IntPtr strChannelName); + private static partial bool AsFbxAnimIsBlendShapeChannelMatch(nint pAnimContext, int channelIndex, string channelName); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimBeginBlendShapeAnimCurve(IntPtr pAnimContext, int channelIndex); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimBeginBlendShapeAnimCurve(nint pAnimContext, int channelIndex); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimEndBlendShapeAnimCurve(IntPtr pAnimContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimEndBlendShapeAnimCurve(nint pAnimContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxAnimAddBlendShapeKeyframe(IntPtr pAnimContext, float time, float value); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxAnimAddBlendShapeKeyframe(nint pAnimContext, float time, float value); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AsFbxMorphCreateContext(); + [LibraryImport(FbxDll.DllName)] + private static partial nint AsFbxMorphCreateContext(); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphInitializeContext(IntPtr pContext, IntPtr pMorphContext, IntPtr pNode); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphInitializeContext(nint pContext, nint pMorphContext, nint pNode); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphDisposeContext(ref IntPtr ppMorphContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphDisposeContext(ref nint ppMorphContext); - private static void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, string channelName) - { - using (var channelNameUtf8 = new Utf8StringHandle(channelName)) - { - AsFbxMorphAddBlendShapeChannel(pContext, pMorphContext, channelNameUtf8.DangerousGetHandle()); - } - } + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial void AsFbxMorphAddBlendShapeChannel(nint pContext, nint pMorphContext, string channelName); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName); + [LibraryImport(FbxDll.DllName, StringMarshalling = StringMarshalling.Utf8)] + private static partial void AsFbxMorphAddBlendShapeChannelShape(nint pContext, nint pMorphContext, float weight, string shapeName); - private static void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, string shapeName) - { - using (var shapeNameUtf8 = new Utf8StringHandle(shapeName)) - { - AsFbxMorphAddBlendShapeChannelShape(pContext, pMorphContext, weight, shapeNameUtf8.DangerousGetHandle()); - } - } + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphCopyBlendShapeControlPoints(nint pMorphContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, IntPtr strShapeName); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphSetBlendShapeVertex(nint pMorphContext, uint index, float x, float y, float z); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphCopyBlendShapeControlPointsNormal(nint pMorphContext); - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphCopyBlendShapeControlPointsNormal(IntPtr pMorphContext); - - [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void AsFbxMorphSetBlendShapeVertexNormal(IntPtr pMorphContext, uint index, float x, float y, float z); + [LibraryImport(FbxDll.DllName)] + private static partial void AsFbxMorphSetBlendShapeVertexNormal(nint pMorphContext, uint index, float x, float y, float z); } } diff --git a/AssetStudioFBXWrapper/FbxExporterContext.cs b/AssetStudioFBXWrapper/FbxExporterContext.cs index 6c4ed7c..75b437c 100644 --- a/AssetStudioFBXWrapper/FbxExporterContext.cs +++ b/AssetStudioFBXWrapper/FbxExporterContext.cs @@ -9,17 +9,17 @@ namespace AssetStudio.FbxInterop internal sealed partial class FbxExporterContext : IDisposable { - private IntPtr _pContext; - private readonly Dictionary _frameToNode; - private readonly List> _createdMaterials; - private readonly Dictionary _createdTextures; + private nint _pContext; + private readonly Dictionary _frameToNode; + private readonly List> _createdMaterials; + private readonly Dictionary _createdTextures; public FbxExporterContext() { _pContext = AsFbxCreateContext(); - _frameToNode = new Dictionary(); - _createdMaterials = new List>(); - _createdTextures = new Dictionary(); + _frameToNode = new Dictionary(); + _createdMaterials = new List>(); + _createdTextures = new Dictionary(); } ~FbxExporterContext() @@ -98,9 +98,9 @@ namespace AssetStudio.FbxInterop { var rootNode = AsFbxGetSceneRootNode(_pContext); - Debug.Assert(rootNode != IntPtr.Zero); + Debug.Assert(rootNode != nint.Zero); - var nodeStack = new Stack(); + var nodeStack = new Stack(); var frameStack = new Stack(); nodeStack.Push(rootNode); @@ -140,7 +140,7 @@ namespace AssetStudio.FbxInterop if (_frameToNode.TryGetValue(frame, out var node)) { - Debug.Assert(node != IntPtr.Zero); + Debug.Assert(node != nint.Zero); if (castToBone) { @@ -181,11 +181,11 @@ namespace AssetStudio.FbxInterop ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps); } - private IntPtr ExportTexture(ImportedTexture texture) + private nint ExportTexture(ImportedTexture texture) { if (texture == null) { - return IntPtr.Zero; + return nint.Zero; } if (_createdTextures.ContainsKey(texture.Name)) @@ -207,7 +207,7 @@ namespace AssetStudio.FbxInterop return pTex; } - private void ExportMesh(ImportedFrame rootFrame, List materialList, List textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps) + private void ExportMesh(ImportedFrame rootFrame, List materialList, List textureList, nint frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps) { var boneList = importedMesh.BoneList; var totalBoneCount = 0; @@ -218,7 +218,7 @@ namespace AssetStudio.FbxInterop hasBones = true; } - var pClusterArray = IntPtr.Zero; + var pClusterArray = nint.Zero; try { @@ -239,7 +239,7 @@ namespace AssetStudio.FbxInterop } else { - AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero); + AsFbxMeshAddCluster(pClusterArray, nint.Zero); } } } @@ -287,7 +287,7 @@ namespace AssetStudio.FbxInterop if (mat != null) { var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name); - IntPtr pMat; + nint pMat; if (foundMat >= 0) { @@ -303,7 +303,7 @@ namespace AssetStudio.FbxInterop pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency); - _createdMaterials.Add(new KeyValuePair(mat.Name, pMat)); + _createdMaterials.Add(new KeyValuePair(mat.Name, pMat)); } materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat); @@ -315,7 +315,7 @@ namespace AssetStudio.FbxInterop var tex = ImportedHelpers.FindTexture(texture.Name, textureList); var pTexture = ExportTexture(tex); - if (pTexture != IntPtr.Zero) + if (pTexture != nint.Zero) { switch (texture.Dest) { @@ -406,7 +406,7 @@ namespace AssetStudio.FbxInterop if (hasBones) { - IntPtr pSkinContext = IntPtr.Zero; + nint pSkinContext = nint.Zero; try { @@ -471,7 +471,7 @@ namespace AssetStudio.FbxInterop return; } - var pAnimContext = IntPtr.Zero; + var pAnimContext = nint.Zero; try { @@ -502,7 +502,7 @@ namespace AssetStudio.FbxInterop } } - private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, IntPtr pAnimContext, float filterPrecision) + private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, nint pAnimContext, float filterPrecision) { foreach (var track in parser.TrackList) { @@ -593,7 +593,7 @@ namespace AssetStudio.FbxInterop var pNode = _frameToNode[frame]; - var pMorphContext = IntPtr.Zero; + var pMorphContext = nint.Zero; try { diff --git a/AssetStudioGUI/AssetStudioGUI.csproj b/AssetStudioGUI/AssetStudioGUI.csproj index aede71e..17bbab2 100644 --- a/AssetStudioGUI/AssetStudioGUI.csproj +++ b/AssetStudioGUI/AssetStudioGUI.csproj @@ -2,12 +2,12 @@ WinExe - net6.0-windows + net7.0-windows true Resources\as.ico - 0.18.60 - 0.18.60 - 0.18.60 + 0.80.30 + 0.80.30 + 0.80.30 Copyright © Razmoth 2022; Copyright © Perfare 2018-2022 embedded @@ -17,18 +17,6 @@ - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - ResXFileCodeGenerator @@ -39,6 +27,11 @@ Resources.resx True + + True + True + Settings.settings + @@ -75,13 +68,20 @@ - + Libraries\OpenTK.WinForms.dll - + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + diff --git a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs index c5f6e6c..8353ce1 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs @@ -1,4 +1,6 @@ -namespace AssetStudioGUI +using System; + +namespace AssetStudioGUI { partial class AssetStudioGUIForm { @@ -37,17 +39,21 @@ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.extractFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.extractFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.abortStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayAll = new System.Windows.Forms.ToolStripMenuItem(); - this.enablePreview = new System.Windows.Forms.ToolStripMenuItem(); this.enableResolveDependencies = new System.Windows.Forms.ToolStripMenuItem(); + this.enablePreview = new System.Windows.Forms.ToolStripMenuItem(); this.displayInfo = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox(); - this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem18 = new System.Windows.Forms.ToolStripMenuItem(); this.specifyGame = new System.Windows.Forms.ToolStripComboBox(); - this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem19 = new System.Windows.Forms.ToolStripMenuItem(); this.specifyAIVersion = new System.Windows.Forms.ToolStripComboBox(); + this.toolStripMenuItem23 = new System.Windows.Forms.ToolStripMenuItem(); this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem(); this.modelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportAllObjectssplitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); @@ -71,6 +77,10 @@ this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem24 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); @@ -81,10 +91,20 @@ this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.console = new System.Windows.Forms.ToolStripMenuItem(); + this.enableConsole = new System.Windows.Forms.ToolStripMenuItem(); + this.clearConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.miscToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.buildCABMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.buildAssetMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.assetHelpersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.cABMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CABMapNameComboBox = new System.Windows.Forms.ToolStripComboBox(); + this.toolStripMenuItem20 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem21 = new System.Windows.Forms.ToolStripMenuItem(); + this.assetMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.assetMapNameTextBox = new System.Windows.Forms.ToolStripTextBox(); + this.toolStripMenuItem22 = new System.Windows.Forms.ToolStripMenuItem(); + this.assetMapTypeComboBox = new System.Windows.Forms.ToolStripComboBox(); + this.loadAIToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); @@ -92,16 +112,16 @@ this.treeSearch = new System.Windows.Forms.TextBox(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.assetListView = new System.Windows.Forms.ListView(); - this.columnHeaderName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeaderContainer = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeaderPathID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeaderSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderName = new System.Windows.Forms.ColumnHeader(); + this.columnHeaderContainer = new System.Windows.Forms.ColumnHeader(); + this.columnHeaderType = new System.Windows.Forms.ColumnHeader(); + this.columnHeaderPathID = new System.Windows.Forms.ColumnHeader(); + this.columnHeaderSize = new System.Windows.Forms.ColumnHeader(); this.listSearch = new System.Windows.Forms.TextBox(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.classesListView = new System.Windows.Forms.ListView(); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this.progressbarPanel = new System.Windows.Forms.Panel(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.tabControl2 = new System.Windows.Forms.TabControl(); @@ -179,7 +199,10 @@ this.loadFolderToolStripMenuItem, this.toolStripMenuItem1, this.extractFileToolStripMenuItem, - this.extractFolderToolStripMenuItem}); + this.extractFolderToolStripMenuItem, + this.toolStripSeparator6, + this.resetToolStripMenuItem, + this.abortStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; @@ -217,16 +240,36 @@ this.extractFolderToolStripMenuItem.Text = "Extract folder"; this.extractFolderToolStripMenuItem.Click += new System.EventHandler(this.extractFolderToolStripMenuItem_Click); // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(141, 6); + // + // resetToolStripMenuItem + // + this.resetToolStripMenuItem.Name = "resetToolStripMenuItem"; + this.resetToolStripMenuItem.Size = new System.Drawing.Size(144, 22); + this.resetToolStripMenuItem.Text = "Reset"; + this.resetToolStripMenuItem.Click += new System.EventHandler(this.resetToolStripMenuItem_Click); + // + // abortStripMenuItem + // + this.abortStripMenuItem.Name = "abortStripMenuItem"; + this.abortStripMenuItem.Size = new System.Drawing.Size(144, 22); + this.abortStripMenuItem.Text = "Abort"; + this.abortStripMenuItem.Click += new System.EventHandler(this.abortStripMenuItem_Click); + // // optionsToolStripMenuItem // this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.displayAll, - this.enablePreview, this.enableResolveDependencies, + this.enablePreview, this.displayInfo, this.toolStripMenuItem14, - this.toolStripMenuItem17, - this.toolStripMenuItem16, + this.toolStripMenuItem18, + this.toolStripMenuItem19, + this.toolStripMenuItem23, this.showExpOpt}); this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; this.optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); @@ -242,6 +285,18 @@ "t the RAW file."; this.displayAll.CheckedChanged += new System.EventHandler(this.displayAll_CheckedChanged); // + // enableResolveDependencies + // + this.enableResolveDependencies.Checked = true; + this.enableResolveDependencies.CheckOnClick = true; + this.enableResolveDependencies.CheckState = System.Windows.Forms.CheckState.Checked; + this.enableResolveDependencies.Name = "enableResolveDependencies"; + this.enableResolveDependencies.Size = new System.Drawing.Size(225, 22); + this.enableResolveDependencies.Text = "Enable resolve dependencies"; + this.enableResolveDependencies.ToolTipText = "Toggle the behaviour of loading assets.\nDisable to load file(s) without its depen" + + "dencies."; + this.enableResolveDependencies.CheckedChanged += new System.EventHandler(this.enableResolveDependencies_CheckedChanged); + // // enablePreview // this.enablePreview.Checked = true; @@ -254,17 +309,6 @@ "etc.\r\nDisable preview if you have performance or compatibility issues."; this.enablePreview.CheckedChanged += new System.EventHandler(this.enablePreview_Check); // - // enableResolveDependencies - // - this.enableResolveDependencies.Checked = true; - this.enableResolveDependencies.CheckOnClick = true; - this.enableResolveDependencies.CheckState = System.Windows.Forms.CheckState.Checked; - this.enableResolveDependencies.Name = "enableResolveDependencies"; - this.enableResolveDependencies.Size = new System.Drawing.Size(225, 22); - this.enableResolveDependencies.Text = "Enable resolve dependencies"; - this.enableResolveDependencies.ToolTipText = "Toggle the behaviour of loading assets.\nDisable to load file(s) without its dependencies."; - this.enableResolveDependencies.CheckedChanged += new System.EventHandler(this.enableResolveDependencies_CheckedChanged); - // // displayInfo // this.displayInfo.Checked = true; @@ -287,17 +331,17 @@ // // specifyUnityVersion // - this.specifyUnityVersion.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F); + this.specifyUnityVersion.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.specifyUnityVersion.Name = "specifyUnityVersion"; this.specifyUnityVersion.Size = new System.Drawing.Size(100, 23); // - // toolStripMenuItem17 + // toolStripMenuItem18 // - this.toolStripMenuItem17.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem18.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.specifyGame}); - this.toolStripMenuItem17.Name = "toolStripMenuItem17"; - this.toolStripMenuItem17.Size = new System.Drawing.Size(225, 22); - this.toolStripMenuItem17.Text = "Specify Game"; + this.toolStripMenuItem18.Name = "toolStripMenuItem18"; + this.toolStripMenuItem18.Size = new System.Drawing.Size(225, 22); + this.toolStripMenuItem18.Text = "Specify Game"; // // specifyGame // @@ -305,14 +349,14 @@ this.specifyGame.Name = "specifyGame"; this.specifyGame.Size = new System.Drawing.Size(121, 23); // - // toolStripMenuItem16 + // toolStripMenuItem19 // - this.toolStripMenuItem16.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem19.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.specifyAIVersion}); - this.toolStripMenuItem16.Name = "toolStripMenuItem16"; - this.toolStripMenuItem16.Size = new System.Drawing.Size(225, 22); - this.toolStripMenuItem16.Text = "Specify AI version"; - this.toolStripMenuItem16.DropDownOpening += new System.EventHandler(this.toolStripMenuItem16_DropDownOpening); + this.toolStripMenuItem19.Name = "toolStripMenuItem19"; + this.toolStripMenuItem19.Size = new System.Drawing.Size(225, 22); + this.toolStripMenuItem19.Text = "Specify AI version"; + this.toolStripMenuItem19.DropDownOpening += new System.EventHandler(this.toolStripMenuItem19_DropDownOpening); // // specifyAIVersion // @@ -321,7 +365,13 @@ "None"}); this.specifyAIVersion.Name = "specifyAIVersion"; this.specifyAIVersion.Size = new System.Drawing.Size(121, 23); - this.specifyAIVersion.SelectedIndexChanged += new System.EventHandler(this.toolStripComboBox1_SelectedIndexChanged); + // + // toolStripMenuItem23 + // + this.toolStripMenuItem23.Name = "toolStripMenuItem23"; + this.toolStripMenuItem23.Size = new System.Drawing.Size(225, 22); + this.toolStripMenuItem23.Text = "Specify CNUnity Key"; + this.toolStripMenuItem23.Click += new System.EventHandler(this.toolStripMenuItem23_Click); // // showExpOpt // @@ -394,6 +444,7 @@ this.toolStripSeparator4, this.toolStripMenuItem2, this.toolStripMenuItem3, + this.toolStripMenuItem16, this.toolStripSeparator2, this.toolStripMenuItem10}); this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; @@ -482,24 +533,55 @@ // toolStripMenuItem7 // this.toolStripMenuItem7.Name = "toolStripMenuItem7"; - this.toolStripMenuItem7.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem7.Size = new System.Drawing.Size(180, 22); this.toolStripMenuItem7.Text = "All assets"; this.toolStripMenuItem7.Click += new System.EventHandler(this.toolStripMenuItem7_Click); // // toolStripMenuItem8 // this.toolStripMenuItem8.Name = "toolStripMenuItem8"; - this.toolStripMenuItem8.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem8.Size = new System.Drawing.Size(180, 22); this.toolStripMenuItem8.Text = "Selected assets"; this.toolStripMenuItem8.Click += new System.EventHandler(this.toolStripMenuItem8_Click); // // toolStripMenuItem9 // this.toolStripMenuItem9.Name = "toolStripMenuItem9"; - this.toolStripMenuItem9.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem9.Size = new System.Drawing.Size(180, 22); this.toolStripMenuItem9.Text = "Filtered assets"; this.toolStripMenuItem9.Click += new System.EventHandler(this.toolStripMenuItem9_Click); // + // toolStripMenuItem16 + // + this.toolStripMenuItem16.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem17, + this.toolStripMenuItem24, + this.toolStripMenuItem25}); + this.toolStripMenuItem16.Name = "toolStripMenuItem16"; + this.toolStripMenuItem16.Size = new System.Drawing.Size(266, 22); + this.toolStripMenuItem16.Text = "JSON"; + // + // toolStripMenuItem17 + // + this.toolStripMenuItem17.Name = "toolStripMenuItem17"; + this.toolStripMenuItem17.Size = new System.Drawing.Size(180, 22); + this.toolStripMenuItem17.Text = "All assets"; + this.toolStripMenuItem17.Click += new System.EventHandler(this.toolStripMenuItem17_Click); + // + // toolStripMenuItem24 + // + this.toolStripMenuItem24.Name = "toolStripMenuItem24"; + this.toolStripMenuItem24.Size = new System.Drawing.Size(180, 22); + this.toolStripMenuItem24.Text = "Selected assets"; + this.toolStripMenuItem24.Click += new System.EventHandler(this.toolStripMenuItem24_Click); + // + // toolStripMenuItem25 + // + this.toolStripMenuItem25.Name = "toolStripMenuItem25"; + this.toolStripMenuItem25.Size = new System.Drawing.Size(180, 22); + this.toolStripMenuItem25.Text = "Filtered assets"; + this.toolStripMenuItem25.Click += new System.EventHandler(this.toolStripMenuItem25_Click); + // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; @@ -550,7 +632,7 @@ this.allToolStripMenuItem.CheckOnClick = true; this.allToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.allToolStripMenuItem.Name = "allToolStripMenuItem"; - this.allToolStripMenuItem.Size = new System.Drawing.Size(88, 22); + this.allToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.allToolStripMenuItem.Text = "All"; this.allToolStripMenuItem.Click += new System.EventHandler(this.typeToolStripMenuItem_Click); // @@ -559,7 +641,8 @@ this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem15, this.exportClassStructuresMenuItem, - this.console}); + this.enableConsole, + this.clearConsoleToolStripMenuItem}); this.debugMenuItem.Name = "debugMenuItem"; this.debugMenuItem.Size = new System.Drawing.Size(54, 20); this.debugMenuItem.Text = "Debug"; @@ -581,39 +664,113 @@ this.exportClassStructuresMenuItem.Text = "Export class structures"; this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click); // - // console + // enableConsole // - this.console.Checked = true; - this.console.CheckOnClick = true; - this.console.CheckState = System.Windows.Forms.CheckState.Checked; - this.console.Name = "console"; - this.console.Size = new System.Drawing.Size(191, 22); - this.console.Text = "Enable Console"; - this.console.ToolTipText = "Check this option to log all events on a debug console."; - this.console.CheckedChanged += new System.EventHandler(this.console_CheckedChanged); + this.enableConsole.Checked = true; + this.enableConsole.CheckOnClick = true; + this.enableConsole.CheckState = System.Windows.Forms.CheckState.Checked; + this.enableConsole.Name = "enableConsole"; + this.enableConsole.Size = new System.Drawing.Size(191, 22); + this.enableConsole.Text = "Enable Console"; + this.enableConsole.CheckedChanged += new System.EventHandler(this.enableConsole_CheckedChanged); + // + // clearConsoleToolStripMenuItem + // + this.clearConsoleToolStripMenuItem.Name = "clearConsoleToolStripMenuItem"; + this.clearConsoleToolStripMenuItem.Size = new System.Drawing.Size(191, 22); + this.clearConsoleToolStripMenuItem.Text = "Clear Console"; + this.clearConsoleToolStripMenuItem.Click += new System.EventHandler(this.clearConsoleToolStripMenuItem_Click); // // miscToolStripMenuItem // this.miscToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.buildCABMapToolStripMenuItem, - this.buildAssetMapToolStripMenuItem}); + this.assetHelpersToolStripMenuItem, + this.loadAIToolStripMenuItem}); this.miscToolStripMenuItem.Name = "miscToolStripMenuItem"; this.miscToolStripMenuItem.Size = new System.Drawing.Size(47, 20); this.miscToolStripMenuItem.Text = "Misc."; // - // buildCABMapToolStripMenuItem + // assetHelpersToolStripMenuItem // - this.buildCABMapToolStripMenuItem.Name = "buildCABMapToolStripMenuItem"; - this.buildCABMapToolStripMenuItem.Size = new System.Drawing.Size(156, 22); - this.buildCABMapToolStripMenuItem.Text = "Build CABMap"; - this.buildCABMapToolStripMenuItem.Click += new System.EventHandler(this.buildCABMapToolStripMenuItem_Click); + this.assetHelpersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.cABMapToolStripMenuItem, + this.assetMapToolStripMenuItem}); + this.assetHelpersToolStripMenuItem.Name = "assetHelpersToolStripMenuItem"; + this.assetHelpersToolStripMenuItem.Size = new System.Drawing.Size(145, 22); + this.assetHelpersToolStripMenuItem.Text = "Asset Helpers"; + this.assetHelpersToolStripMenuItem.DropDownOpening += new System.EventHandler(this.assetHelpersToolStripMenuItem_DropDownOpening); // - // buildAssetMapToolStripMenuItem + // cABMapToolStripMenuItem // - this.buildAssetMapToolStripMenuItem.Name = "buildAssetMapToolStripMenuItem"; - this.buildAssetMapToolStripMenuItem.Size = new System.Drawing.Size(156, 22); - this.buildAssetMapToolStripMenuItem.Text = "Build AssetMap"; - this.buildAssetMapToolStripMenuItem.Click += new System.EventHandler(this.buildAssetMapToolStripMenuItem_Click); + this.cABMapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.CABMapNameComboBox, + this.toolStripMenuItem20, + this.toolStripMenuItem21}); + this.cABMapToolStripMenuItem.Name = "cABMapToolStripMenuItem"; + this.cABMapToolStripMenuItem.Size = new System.Drawing.Size(126, 22); + this.cABMapToolStripMenuItem.Text = "CABMap"; + // + // CABMapNameComboBox + // + this.CABMapNameComboBox.Name = "CABMapNameComboBox"; + this.CABMapNameComboBox.Size = new System.Drawing.Size(121, 23); + this.CABMapNameComboBox.ToolTipText = "Enter name of CABMap here"; + // + // toolStripMenuItem20 + // + this.toolStripMenuItem20.Name = "toolStripMenuItem20"; + this.toolStripMenuItem20.Size = new System.Drawing.Size(181, 22); + this.toolStripMenuItem20.Text = "Build CABMap"; + this.toolStripMenuItem20.Click += new System.EventHandler(this.toolStripMenuItem20_Click); + // + // toolStripMenuItem21 + // + this.toolStripMenuItem21.Name = "toolStripMenuItem21"; + this.toolStripMenuItem21.Size = new System.Drawing.Size(181, 22); + this.toolStripMenuItem21.Text = "Clear CABMap"; + this.toolStripMenuItem21.Click += new System.EventHandler(this.toolStripMenuItem21_Click); + // + // assetMapToolStripMenuItem + // + this.assetMapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.assetMapNameTextBox, + this.toolStripMenuItem22, + this.assetMapTypeComboBox}); + this.assetMapToolStripMenuItem.Name = "assetMapToolStripMenuItem"; + this.assetMapToolStripMenuItem.Size = new System.Drawing.Size(126, 22); + this.assetMapToolStripMenuItem.Text = "AssetMap"; + // + // assetMapNameTextBox + // + this.assetMapNameTextBox.Name = "assetMapNameTextBox"; + this.assetMapNameTextBox.Size = new System.Drawing.Size(100, 23); + this.assetMapNameTextBox.ToolTipText = "Enter name of AssetMap here"; + // + // toolStripMenuItem22 + // + this.toolStripMenuItem22.Name = "toolStripMenuItem22"; + this.toolStripMenuItem22.Size = new System.Drawing.Size(181, 22); + this.toolStripMenuItem22.Text = "Build AssetMap"; + this.toolStripMenuItem22.Click += new System.EventHandler(this.toolStripMenuItem22_Click); + // + // assetMapTypeComboBox + // + this.assetMapTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.assetMapTypeComboBox.Name = "assetMapTypeComboBox"; + this.assetMapTypeComboBox.Size = new System.Drawing.Size(121, 23); + this.assetMapTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.assetMapTypeComboBox_SelectedIndexChanged); + // + // loadAIToolStripMenuItem + // + this.loadAIToolStripMenuItem.Name = "loadAIToolStripMenuItem"; + this.loadAIToolStripMenuItem.Size = new System.Drawing.Size(145, 22); + this.loadAIToolStripMenuItem.Text = "Load AI"; + this.loadAIToolStripMenuItem.Click += new System.EventHandler(this.loadAIToolStripMenuItem_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(178, 6); // // splitContainer1 // @@ -657,9 +814,9 @@ // this.tabPage1.Controls.Add(this.sceneTreeView); this.tabPage1.Controls.Add(this.treeSearch); - this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Location = new System.Drawing.Point(4, 24); this.tabPage1.Name = "tabPage1"; - this.tabPage1.Size = new System.Drawing.Size(472, 609); + this.tabPage1.Size = new System.Drawing.Size(472, 607); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Scene Hierarchy"; this.tabPage1.UseVisualStyleBackColor = true; @@ -669,9 +826,9 @@ this.sceneTreeView.CheckBoxes = true; this.sceneTreeView.Dock = System.Windows.Forms.DockStyle.Fill; this.sceneTreeView.HideSelection = false; - this.sceneTreeView.Location = new System.Drawing.Point(0, 20); + this.sceneTreeView.Location = new System.Drawing.Point(0, 23); this.sceneTreeView.Name = "sceneTreeView"; - this.sceneTreeView.Size = new System.Drawing.Size(472, 589); + this.sceneTreeView.Size = new System.Drawing.Size(472, 584); this.sceneTreeView.TabIndex = 1; this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck); // @@ -681,7 +838,7 @@ this.treeSearch.ForeColor = System.Drawing.SystemColors.GrayText; this.treeSearch.Location = new System.Drawing.Point(0, 0); this.treeSearch.Name = "treeSearch"; - this.treeSearch.Size = new System.Drawing.Size(472, 20); + this.treeSearch.Size = new System.Drawing.Size(472, 23); this.treeSearch.TabIndex = 0; this.treeSearch.Text = " Search "; this.treeSearch.TextChanged += new System.EventHandler(this.treeSearch_TextChanged); @@ -693,9 +850,9 @@ // this.tabPage2.Controls.Add(this.assetListView); this.tabPage2.Controls.Add(this.listSearch); - this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Location = new System.Drawing.Point(4, 24); this.tabPage2.Name = "tabPage2"; - this.tabPage2.Size = new System.Drawing.Size(472, 609); + this.tabPage2.Size = new System.Drawing.Size(472, 607); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Asset List"; this.tabPage2.UseVisualStyleBackColor = true; @@ -711,10 +868,9 @@ this.assetListView.Dock = System.Windows.Forms.DockStyle.Fill; this.assetListView.FullRowSelect = true; this.assetListView.GridLines = true; - this.assetListView.HideSelection = false; - this.assetListView.Location = new System.Drawing.Point(0, 20); + this.assetListView.Location = new System.Drawing.Point(0, 23); this.assetListView.Name = "assetListView"; - this.assetListView.Size = new System.Drawing.Size(472, 589); + this.assetListView.Size = new System.Drawing.Size(472, 584); this.assetListView.TabIndex = 1; this.assetListView.UseCompatibleStateImageBehavior = false; this.assetListView.View = System.Windows.Forms.View.Details; @@ -754,7 +910,7 @@ this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText; this.listSearch.Location = new System.Drawing.Point(0, 0); this.listSearch.Name = "listSearch"; - this.listSearch.Size = new System.Drawing.Size(472, 20); + this.listSearch.Size = new System.Drawing.Size(472, 23); this.listSearch.TabIndex = 0; this.listSearch.Text = " Filter "; this.listSearch.TextChanged += new System.EventHandler(this.ListSearchTextChanged); @@ -764,9 +920,9 @@ // tabPage3 // this.tabPage3.Controls.Add(this.classesListView); - this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Location = new System.Drawing.Point(4, 24); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(472, 609); + this.tabPage3.Size = new System.Drawing.Size(472, 607); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "Asset Classes"; this.tabPage3.UseVisualStyleBackColor = true; @@ -778,11 +934,10 @@ this.columnHeader2}); this.classesListView.Dock = System.Windows.Forms.DockStyle.Fill; this.classesListView.FullRowSelect = true; - this.classesListView.HideSelection = false; this.classesListView.Location = new System.Drawing.Point(0, 0); this.classesListView.MultiSelect = false; this.classesListView.Name = "classesListView"; - this.classesListView.Size = new System.Drawing.Size(472, 609); + this.classesListView.Size = new System.Drawing.Size(472, 607); this.classesListView.TabIndex = 0; this.classesListView.UseCompatibleStateImageBehavior = false; this.classesListView.View = System.Windows.Forms.View.Details; @@ -834,9 +989,9 @@ // tabPage4 // this.tabPage4.Controls.Add(this.previewPanel); - this.tabPage4.Location = new System.Drawing.Point(4, 22); + this.tabPage4.Location = new System.Drawing.Point(4, 24); this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(768, 607); + this.tabPage4.Size = new System.Drawing.Size(768, 605); this.tabPage4.TabIndex = 0; this.tabPage4.Text = "Preview"; this.tabPage4.UseVisualStyleBackColor = true; @@ -855,7 +1010,7 @@ this.previewPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.previewPanel.Location = new System.Drawing.Point(0, 0); this.previewPanel.Name = "previewPanel"; - this.previewPanel.Size = new System.Drawing.Size(768, 607); + this.previewPanel.Size = new System.Drawing.Size(768, 605); this.previewPanel.TabIndex = 1; this.previewPanel.Resize += new System.EventHandler(this.preview_Resize); // @@ -866,7 +1021,7 @@ this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.assetInfoLabel.Location = new System.Drawing.Point(4, 7); this.assetInfoLabel.Name = "assetInfoLabel"; - this.assetInfoLabel.Size = new System.Drawing.Size(0, 13); + this.assetInfoLabel.Size = new System.Drawing.Size(0, 15); this.assetInfoLabel.TabIndex = 0; // // FMODpanel @@ -885,7 +1040,7 @@ this.FMODpanel.Dock = System.Windows.Forms.DockStyle.Fill; this.FMODpanel.Location = new System.Drawing.Point(0, 0); this.FMODpanel.Name = "FMODpanel"; - this.FMODpanel.Size = new System.Drawing.Size(768, 607); + this.FMODpanel.Size = new System.Drawing.Size(768, 605); this.FMODpanel.TabIndex = 2; this.FMODpanel.Visible = false; // @@ -895,7 +1050,7 @@ this.FMODcopyright.ForeColor = System.Drawing.SystemColors.ControlLight; this.FMODcopyright.Location = new System.Drawing.Point(214, 337); this.FMODcopyright.Name = "FMODcopyright"; - this.FMODcopyright.Size = new System.Drawing.Size(283, 13); + this.FMODcopyright.Size = new System.Drawing.Size(316, 15); this.FMODcopyright.TabIndex = 9; this.FMODcopyright.Text = "Audio Engine supplied by FMOD by Firelight Technologies."; // @@ -905,7 +1060,7 @@ this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.FMODinfoLabel.Location = new System.Drawing.Point(269, 235); this.FMODinfoLabel.Name = "FMODinfoLabel"; - this.FMODinfoLabel.Size = new System.Drawing.Size(0, 13); + this.FMODinfoLabel.Size = new System.Drawing.Size(0, 15); this.FMODinfoLabel.TabIndex = 8; // // FMODtimerLabel @@ -914,7 +1069,7 @@ this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.FMODtimerLabel.Location = new System.Drawing.Point(460, 235); this.FMODtimerLabel.Name = "FMODtimerLabel"; - this.FMODtimerLabel.Size = new System.Drawing.Size(78, 13); + this.FMODtimerLabel.Size = new System.Drawing.Size(78, 15); this.FMODtimerLabel.TabIndex = 7; this.FMODtimerLabel.Text = "0:00.0 / 0:00.0"; // @@ -924,7 +1079,7 @@ this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235); this.FMODstatusLabel.Name = "FMODstatusLabel"; - this.FMODstatusLabel.Size = new System.Drawing.Size(47, 13); + this.FMODstatusLabel.Size = new System.Drawing.Size(51, 15); this.FMODstatusLabel.TabIndex = 6; this.FMODstatusLabel.Text = "Stopped"; // @@ -1001,14 +1156,14 @@ this.fontPreviewBox.Location = new System.Drawing.Point(0, 0); this.fontPreviewBox.Name = "fontPreviewBox"; this.fontPreviewBox.ReadOnly = true; - this.fontPreviewBox.Size = new System.Drawing.Size(768, 607); + this.fontPreviewBox.Size = new System.Drawing.Size(768, 605); this.fontPreviewBox.TabIndex = 0; this.fontPreviewBox.Text = resources.GetString("fontPreviewBox.Text"); this.fontPreviewBox.Visible = false; this.fontPreviewBox.WordWrap = false; // - // glControl1 - // + // glControl + // this.glControl.API = OpenTK.Windowing.Common.ContextAPI.OpenGL; this.glControl.APIVersion = new System.Version(4, 6, 0, 0); this.glControl.BackColor = System.Drawing.SystemColors.ControlDarkDark; @@ -1016,27 +1171,28 @@ this.glControl.Flags = OpenTK.Windowing.Common.ContextFlags.Default; this.glControl.IsEventDriven = true; this.glControl.Location = new System.Drawing.Point(0, 0); - this.glControl.Name = "glControl1"; - this.glControl.Size = new System.Drawing.Size(768, 607); + this.glControl.Name = "glControl"; + this.glControl.Profile = OpenTK.Windowing.Common.ContextProfile.Core; + this.glControl.Size = new System.Drawing.Size(768, 605); this.glControl.TabIndex = 4; this.glControl.Visible = false; - this.glControl.Load += new System.EventHandler(this.glControl1_Load); - this.glControl.Paint += new System.Windows.Forms.PaintEventHandler(this.glControl1_Paint); - this.glControl.MouseDown += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseDown); - this.glControl.MouseMove += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseMove); - this.glControl.MouseUp += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseUp); - this.glControl.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseWheel); + this.glControl.Load += new System.EventHandler(this.glControl_Load); + this.glControl.Paint += new System.Windows.Forms.PaintEventHandler(this.glControl_Paint); + this.glControl.MouseDown += new System.Windows.Forms.MouseEventHandler(this.glControl_MouseDown); + this.glControl.MouseMove += new System.Windows.Forms.MouseEventHandler(this.glControl_MouseMove); + this.glControl.MouseUp += new System.Windows.Forms.MouseEventHandler(this.glControl_MouseUp); + this.glControl.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.glControl_MouseWheel); // // textPreviewBox // this.textPreviewBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.textPreviewBox.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textPreviewBox.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.textPreviewBox.Location = new System.Drawing.Point(0, 0); this.textPreviewBox.Multiline = true; this.textPreviewBox.Name = "textPreviewBox"; this.textPreviewBox.ReadOnly = true; this.textPreviewBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.textPreviewBox.Size = new System.Drawing.Size(768, 607); + this.textPreviewBox.Size = new System.Drawing.Size(768, 605); this.textPreviewBox.TabIndex = 2; this.textPreviewBox.Visible = false; this.textPreviewBox.WordWrap = false; @@ -1049,7 +1205,7 @@ this.classTextBox.Name = "classTextBox"; this.classTextBox.ReadOnly = true; this.classTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.classTextBox.Size = new System.Drawing.Size(768, 607); + this.classTextBox.Size = new System.Drawing.Size(768, 605); this.classTextBox.TabIndex = 3; this.classTextBox.Visible = false; this.classTextBox.WordWrap = false; @@ -1057,9 +1213,9 @@ // tabPage5 // this.tabPage5.Controls.Add(this.dumpTextBox); - this.tabPage5.Location = new System.Drawing.Point(4, 22); + this.tabPage5.Location = new System.Drawing.Point(4, 24); this.tabPage5.Name = "tabPage5"; - this.tabPage5.Size = new System.Drawing.Size(768, 607); + this.tabPage5.Size = new System.Drawing.Size(768, 605); this.tabPage5.TabIndex = 1; this.tabPage5.Text = "Dump"; this.tabPage5.UseVisualStyleBackColor = true; @@ -1072,7 +1228,7 @@ this.dumpTextBox.Name = "dumpTextBox"; this.dumpTextBox.ReadOnly = true; this.dumpTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.dumpTextBox.Size = new System.Drawing.Size(768, 607); + this.dumpTextBox.Size = new System.Drawing.Size(768, 605); this.dumpTextBox.TabIndex = 0; this.dumpTextBox.WordWrap = false; // @@ -1303,15 +1459,33 @@ private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14; private System.Windows.Forms.ToolStripTextBox specifyUnityVersion; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15; - private System.Windows.Forms.ToolStripMenuItem miscToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem buildCABMapToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem console; - private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem16; - private System.Windows.Forms.ToolStripComboBox specifyAIVersion; - private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem17; - private System.Windows.Forms.ToolStripComboBox specifyGame; - private System.Windows.Forms.ToolStripMenuItem buildAssetMapToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem enableResolveDependencies; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem18; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem19; + private System.Windows.Forms.ToolStripComboBox specifyGame; + private System.Windows.Forms.ToolStripComboBox specifyAIVersion; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem16; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem17; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem24; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem25; + private System.Windows.Forms.ToolStripMenuItem enableConsole; + private System.Windows.Forms.ToolStripMenuItem miscToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem assetHelpersToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem20; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem22; + private System.Windows.Forms.ToolStripComboBox CABMapNameComboBox; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem23; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ToolStripMenuItem resetToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem abortStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem21; + private System.Windows.Forms.ToolStripMenuItem cABMapToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem assetMapToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem loadAIToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem clearConsoleToolStripMenuItem; + private System.Windows.Forms.ToolStripTextBox assetMapNameTextBox; + private System.Windows.Forms.ToolStripComboBox assetMapTypeComboBox; } } diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs index c38fad6..3c84593 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.cs @@ -1,6 +1,5 @@ using AssetStudio; using Newtonsoft.Json; -using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; @@ -11,9 +10,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; -using System.Runtime.Serialization.Formatters.Binary; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Timers; @@ -23,8 +20,9 @@ using Font = AssetStudio.Font; using Vector3 = OpenTK.Mathematics.Vector3; using Vector4 = OpenTK.Mathematics.Vector4; using Matrix4 = OpenTK.Mathematics.Matrix4; +using OpenTK.Graphics; using OpenTK.Mathematics; -using SpirV; +using Newtonsoft.Json.Converters; namespace AssetStudioGUI { @@ -89,9 +87,6 @@ namespace AssetStudioGUI private GUILogger logger; - [DllImport("gdi32.dll")] - private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts); - public AssetStudioGUIForm() { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); @@ -99,26 +94,34 @@ namespace AssetStudioGUI Text = $"Studio v{Application.ProductVersion}"; delayTimer = new System.Timers.Timer(800); delayTimer.Elapsed += new ElapsedEventHandler(delayTimer_Elapsed); - console.Checked = Properties.Settings.Default.console; + InitializeExportOptions(); + InitializeProgressBar(); + InitializeLogger(); + InitalizeOptions(); + FMODinit(); + } + + private void InitializeExportOptions() + { + enableConsole.Checked = Properties.Settings.Default.enableConsole; displayAll.Checked = Properties.Settings.Default.displayAll; displayInfo.Checked = Properties.Settings.Default.displayInfo; enablePreview.Checked = Properties.Settings.Default.enablePreview; enableResolveDependencies.Checked = Properties.Settings.Default.enableResolveDependencies; - assetsManager.ResolveDependancies = enableResolveDependencies.Checked; - AssetBundle.Exportable = Properties.Settings.Default.exportAssetBundle; - IndexObject.Exportable = Properties.Settings.Default.exportIndexObject; - Renderer.Parsable = !Properties.Settings.Default.disableRndrr; - Shader.Parsable = !Properties.Settings.Default.disableShader; - MiHoYoBinData.doXOR = Properties.Settings.Default.enableXor; + assetsManager.ResolveDependencies = enableResolveDependencies.Checked; + Renderer.Skipped = Properties.Settings.Default.skipRenderer; + MiHoYoBinData.Exportable = Properties.Settings.Default.exportMiHoYoBinData; + MiHoYoBinData.Encrypted = Properties.Settings.Default.encrypted; MiHoYoBinData.Key = Properties.Settings.Default.key; - FMODinit(); + } + private void InitializeLogger() + { logger = new GUILogger(StatusStripUpdate); - ConsoleHelper.AllocConsole(); ConsoleHelper.SetConsoleTitle("Debug Console"); var handle = ConsoleHelper.GetConsoleWindow(); - if (console.Checked) + if (enableConsole.Checked) { Logger.Default = new ConsoleLogger(); ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_SHOW); @@ -128,16 +131,28 @@ namespace AssetStudioGUI Logger.Default = logger; ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_HIDE); } - Progress.Default = new Progress(SetProgressBarValue); - Studio.StatusStripUpdate = StatusStripUpdate; - specifyGame.Items.AddRange(GameManager.GetGames()); - Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame); - specifyGame.SelectedIndex = Properties.Settings.Default.selectedGame; - specifyGame.SelectedIndexChanged += new EventHandler(toolStripComboBox2_SelectedIndexChanged); - Logger.Info($"Target Game is {Studio.Game.Name}"); - CABManager.LoadMap(Studio.Game); } + private void InitializeProgressBar() + { + Progress.Default = new Progress(SetProgressBarValue); + Studio.StatusStripUpdate = StatusStripUpdate; + } + + private void InitalizeOptions() + { + assetMapTypeComboBox.Items.AddRange(Enum.GetValues().Cast().ToArray()); + assetMapTypeComboBox.SelectedIndex = Properties.Settings.Default.selectedAssetMapType; + + specifyGame.Items.AddRange(GameManager.GetGames()); + specifyGame.SelectedIndex = Properties.Settings.Default.selectedGame; + specifyGame.SelectedIndexChanged += new EventHandler(specifyGame_SelectedIndexChanged); + Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame); + Logger.Info($"Target Game type is {Studio.Game.Type}"); + + CABMapNameComboBox.SelectedIndexChanged += new EventHandler(specifyNameComboBox_SelectedIndexChanged); + CNUnityKeyManager.SetKey(Properties.Settings.Default.selectedCNUnityKey); + } private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) @@ -160,6 +175,10 @@ namespace AssetStudioGUI } else { + if (paths.Length == 1 && File.Exists(paths[0]) && Path.GetExtension(paths[0]) == ".txt") + { + paths = File.ReadAllLines(paths[0]); + } await Task.Run(() => assetsManager.LoadFiles(paths)); } BuildAssetStructures(); @@ -174,7 +193,6 @@ namespace AssetStudioGUI ResetForm(); openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]); assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text; - assetsManager.Game = Studio.Game; await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames)); BuildAssetStructures(); } @@ -236,17 +254,22 @@ namespace AssetStudioGUI return; } - (var productName, var treeNodeCollection) = await Task.Run(() => BuildAssetData()); - var typeMap = await Task.Run(() => BuildClassStructure()); + (var productName, var treeNodeCollection) = await Task.Run(BuildAssetData); + var typeMap = await Task.Run(BuildClassStructure); - if (!string.IsNullOrEmpty(productName)) + if (string.IsNullOrEmpty(productName)) { - Text = $"Studio v{Application.ProductVersion} - {productName} - {Path.GetFileName(assetsManager.assetsFileList[0].originalPath)} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}"; - } - else - { - Text = $"Studio v{Application.ProductVersion} - {Studio.Game.Name} - {Path.GetFileName(assetsManager.assetsFileList[0].originalPath)} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}"; - } + if (!Studio.Game.Type.IsNormal()) + { + productName = Studio.Game.Name; + } + else + { + productName = "no productName"; + } + } + + Text = $"Studio v{Application.ProductVersion} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}"; assetListView.VirtualListSize = visibleAssets.Count; @@ -402,24 +425,6 @@ namespace AssetStudioGUI } } - private void console_CheckedChanged(object sender, EventArgs e) - { - Properties.Settings.Default.console = console.Checked; - Properties.Settings.Default.Save(); - - var handle = ConsoleHelper.GetConsoleWindow(); - if (console.Checked) - { - Logger.Default = new ConsoleLogger(); - ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_SHOW); - } - else - { - Logger.Default = logger; - ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_HIDE); - } - } - private void displayAll_CheckedChanged(object sender, EventArgs e) { Properties.Settings.Default.displayAll = displayAll.Checked; @@ -449,6 +454,7 @@ namespace AssetStudioGUI case ClassIDType.Shader: case ClassIDType.TextAsset: case ClassIDType.MonoBehaviour: + case ClassIDType.MiHoYoBinData: textPreviewBox.Visible = !textPreviewBox.Visible; break; case ClassIDType.Font: @@ -492,7 +498,7 @@ namespace AssetStudioGUI Properties.Settings.Default.enableResolveDependencies = enableResolveDependencies.Checked; Properties.Settings.Default.Save(); - assetsManager.ResolveDependancies = enableResolveDependencies.Checked; + assetsManager.ResolveDependencies = enableResolveDependencies.Checked; } private void displayAssetInfo_Check(object sender, EventArgs e) @@ -786,19 +792,21 @@ namespace AssetStudioGUI break; case Animator _: StatusStripUpdate("Can be exported to FBX file."); - goto default; + break; case AnimationClip _: - StatusStripUpdate("Can be exported with Animator or Objects or .anim file."); + StatusStripUpdate("Can be exported with Animator or Objects"); break; case MiHoYoBinData m_MiHoYoBinData: - PreviewText(m_MiHoYoBinData.Str); + PreviewText(m_MiHoYoBinData.AsString); StatusStripUpdate("Can be exported/previewed as JSON if data is a valid JSON (check XOR)."); break; default: var str = assetItem.Asset.Dump(); - if (string.IsNullOrEmpty(str)) + if (Properties.Settings.Default.displayAll || string.IsNullOrEmpty(str)) { - str = JsonConvert.SerializeObject(assetItem.Asset, Formatting.Indented); + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new StringEnumConverter()); + str = JsonConvert.SerializeObject(assetItem.Asset, Formatting.Indented, settings); } if (str != null) { @@ -1002,7 +1010,7 @@ namespace AssetStudioGUI { if (m_Shader.byteSize > 0xFFFFFFF) { - PreviewText("Serialized Shader can't be read"); + PreviewText("Shader is too large to parse"); return; } @@ -1037,8 +1045,8 @@ namespace AssetStudioGUI Marshal.Copy(m_Font.m_FontData, 0, data, m_Font.m_FontData.Length); uint cFonts = 0; - var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts); - if (re != IntPtr.Zero) + var re = FontHelper.AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, nint.Zero, ref cFonts); + if (re != nint.Zero) { using (var pfc = new PrivateFontCollection()) { @@ -1319,6 +1327,7 @@ namespace AssetStudioGUI } FMODreset(); + StatusStripUpdate("Reset successfully !!"); } private void assetListView_MouseClick(object sender, MouseEventArgs e) @@ -1534,6 +1543,20 @@ namespace AssetStudioGUI { ExportAssets(ExportFilter.Filtered, ExportType.Dump); } + private void toolStripMenuItem17_Click(object sender, EventArgs e) + { + ExportAssets(ExportFilter.All, ExportType.JSON); + } + + private void toolStripMenuItem24_Click(object sender, EventArgs e) + { + ExportAssets(ExportFilter.Selected, ExportType.JSON); + } + + private void toolStripMenuItem25_Click(object sender, EventArgs e) + { + ExportAssets(ExportFilter.Filtered, ExportType.JSON); + } private void toolStripMenuItem11_Click(object sender, EventArgs e) { @@ -1678,6 +1701,337 @@ namespace AssetStudioGUI } } + private void toolStripMenuItem15_Click(object sender, EventArgs e) + { + logger.ShowErrorMessage = toolStripMenuItem15.Checked; + } + private async void toolStripMenuItem19_DropDownOpening(object sender, EventArgs e) + { + if (specifyAIVersion.Enabled && await AIVersionManager.FetchVersions()) + { + UpdateVersionList(); + } + } + + private void assetHelpersToolStripMenuItem_DropDownOpening(object sender, EventArgs e) + { + if (assetHelpersToolStripMenuItem.Enabled) + { + CABMapNameComboBox.Items.Clear(); + CABMapNameComboBox.Items.AddRange(AssetsHelper.GetMaps()); + } + } + + private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (specifyAIVersion.SelectedIndex == 0) + { + return; + } + optionsToolStripMenuItem.DropDown.Visible = false; + var version = specifyAIVersion.SelectedItem.ToString(); + + if (version.Contains(' ')) + { + version = version.Split(' ')[0]; + } + + Logger.Info($"Loading AI v{version}"); + InvokeUpdate(specifyAIVersion, false); + var path = await AIVersionManager.FetchAI(version); + await Task.Run(() => ResourceIndex.FromFile(path)); + UpdateContainers(); + UpdateVersionList(); + InvokeUpdate(specifyAIVersion, true); + } + + private void UpdateVersionList() + { + var selectedIndex = specifyAIVersion.SelectedIndex; + specifyAIVersion.Items.Clear(); + specifyAIVersion.Items.Add("None"); + + var versions = AIVersionManager.GetVersions(); + foreach (var version in versions) + { + specifyAIVersion.Items.Add(version.Item1 + (version.Item2 ? " (cached)" : "")); + } + + specifyAIVersion.SelectedIndexChanged -= new EventHandler(toolStripComboBox1_SelectedIndexChanged); + specifyAIVersion.SelectedIndex = selectedIndex; + specifyAIVersion.SelectedIndexChanged += new EventHandler(toolStripComboBox1_SelectedIndexChanged); + } + + private void UpdateContainers() + { + if (exportableAssets.Count > 0) + { + Logger.Info("Updating Containers..."); + assetListView.BeginUpdate(); + foreach (var asset in exportableAssets) + { + if (int.TryParse(asset.Container, out var value)) + { + var last = unchecked((uint)value); + var path = ResourceIndex.GetAssetPath(last); + if (!string.IsNullOrEmpty(path)) + { + asset.Container = path; + asset.SubItems[1].Text = path; + if (asset.Type == ClassIDType.MiHoYoBinData) + { + asset.Text = Path.GetFileNameWithoutExtension(path); + } + } + } + } + assetListView.EndUpdate(); + Logger.Info("Updated !!"); + } + } + + private void InvokeUpdate(ToolStripItem item, bool value) + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { item.Enabled = value; })); + } + else + { + item.Enabled = value; + } + } + + private void tabControl2_SelectedIndexChanged(object sender, EventArgs e) + { + if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null) + { + dumpTextBox.Text = DumpAsset(lastSelectedItem.Asset); + } + } + private void assetMapTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + Properties.Settings.Default.selectedAssetMapType = assetMapTypeComboBox.SelectedIndex; + Properties.Settings.Default.Save(); + } + + private void specifyGame_SelectedIndexChanged(object sender, EventArgs e) + { + optionsToolStripMenuItem.DropDown.Visible = false; + Properties.Settings.Default.selectedGame = specifyGame.SelectedIndex; + Properties.Settings.Default.Save(); + + Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame); + Logger.Info($"Target Game is {Studio.Game.Name}"); + + ResetForm(); + assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text; + assetsManager.Game = Studio.Game; + } + + private async void specifyNameComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + miscToolStripMenuItem.DropDown.Visible = false; + InvokeUpdate(miscToolStripMenuItem, false); + + var name = CABMapNameComboBox.SelectedItem.ToString(); + await Task.Run(() => AssetsHelper.LoadMap(name)); + + ResetForm(); + assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text; + assetsManager.Game = Studio.Game; + + InvokeUpdate(miscToolStripMenuItem, true); + } + + private async void toolStripMenuItem20_Click(object sender, EventArgs e) + { + miscToolStripMenuItem.DropDown.Visible = false; + InvokeUpdate(miscToolStripMenuItem, false); + + var input = CABMapNameComboBox.Text; + var selectedText = CABMapNameComboBox.SelectedText; + var name = ""; + + if (!string.IsNullOrEmpty(selectedText)) + { + name = selectedText; + } + else if (!string.IsNullOrEmpty(input)) + { + if (input.IndexOfAny(Path.GetInvalidFileNameChars()) != -1) + { + Logger.Warning("Name has invalid characters !!"); + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + + name = input; + } + else + { + Logger.Error("CABMap name is empty, please enter any name in ComboBox above"); + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + + if (File.Exists(Path.Combine(AssetsHelper.CABMapName, $"{name}.bin"))) + { + var acceptOverride = MessageBox.Show("CABMap already exist, Do you want to override it ?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (acceptOverride != DialogResult.Yes) + { + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + } + + var openFolderDialog = new OpenFolderDialog(); + openFolderDialog.Title = "Select Game Folder"; + if (openFolderDialog.ShowDialog(this) == DialogResult.OK) + { + Logger.Info("Scanning for files"); + var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); + Logger.Info($"Found {files.Length} files"); + await Task.Run(() => AssetsHelper.BuildCABMap(files, name, openFolderDialog.Folder, Studio.Game)); + } + InvokeUpdate(miscToolStripMenuItem, true); + } + + private void toolStripMenuItem21_Click(object sender, EventArgs e) + { + miscToolStripMenuItem.DropDown.Visible = false; + InvokeUpdate(miscToolStripMenuItem, false); + + var acceptDelete = MessageBox.Show("CABMap will be deleted, this can't be undone, continue ?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (acceptDelete != DialogResult.Yes) + { + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + + var name = CABMapNameComboBox.Text.ToString(); + var path = Path.Combine(AssetsHelper.CABMapName, $"{name}.bin"); + if (File.Exists(path)) + { + File.Delete(path); + Logger.Info($"{name} deleted successfully !!"); + CABMapNameComboBox.SelectedIndexChanged -= new EventHandler(specifyNameComboBox_SelectedIndexChanged); + CABMapNameComboBox.SelectedIndex = 0; + CABMapNameComboBox.SelectedIndexChanged += new EventHandler(specifyNameComboBox_SelectedIndexChanged); + } + + InvokeUpdate(miscToolStripMenuItem, true); + } + + private void toolStripMenuItem23_Click(object sender, EventArgs e) + { + var form = new CNUnityForm(); + form.Show(); + } + + private void resetToolStripMenuItem_Click(object sender, EventArgs e) + { + ResetForm(); + AssetsHelper.Clear(); + } + + private void enableConsole_CheckedChanged(object sender, EventArgs e) + { + Properties.Settings.Default.enableConsole = enableConsole.Checked; + Properties.Settings.Default.Save(); + + var handle = ConsoleHelper.GetConsoleWindow(); + if (enableConsole.Checked) + { + Logger.Default = new ConsoleLogger(); + ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_SHOW); + } + else + { + Logger.Default = logger; + ConsoleHelper.ShowWindow(handle, ConsoleHelper.SW_HIDE); + } + } + + private void abortStripMenuItem_Click(object sender, EventArgs e) + { + Logger.Info("Aborting...."); + assetsManager.tokenSource.Cancel(); + AssetsHelper.tokenSource.Cancel(); + } + + private async void loadAIToolStripMenuItem_Click(object sender, EventArgs e) + { + miscToolStripMenuItem.DropDown.Visible = false; + + var openFileDialog = new OpenFileDialog() { Multiselect = false, Filter = "Asset Index JSON File|*.json" }; + if (openFileDialog.ShowDialog(this) == DialogResult.OK) + { + var path = openFileDialog.FileName; + Logger.Info($"Loading AI..."); + InvokeUpdate(loadAIToolStripMenuItem, false); + await Task.Run(() => ResourceIndex.FromFile(path)); + UpdateContainers(); + InvokeUpdate(loadAIToolStripMenuItem, true); + } + } + + private void clearConsoleToolStripMenuItem_Click(object sender, EventArgs e) + { + Console.Clear(); + } + + private async void toolStripMenuItem22_Click(object sender, EventArgs e) + { + miscToolStripMenuItem.DropDown.Visible = false; + InvokeUpdate(miscToolStripMenuItem, false); + + var input = assetMapNameTextBox.Text; + var exportListType = (ExportListType)assetMapTypeComboBox.SelectedItem; + var name = "assets_map"; + + if (!string.IsNullOrEmpty(input)) + { + if (input.IndexOfAny(Path.GetInvalidFileNameChars()) != -1) + { + Logger.Warning("Name has invalid characters !!"); + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + + name = input; + } + + var openFolderDialog = new OpenFolderDialog(); + openFolderDialog.Title = $"Select Game Folder"; + if (openFolderDialog.ShowDialog(this) == DialogResult.OK) + { + Logger.Info("Scanning for files"); + var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); + Logger.Info($"Found {files.Length} files"); + + var saveFolderDialog = new OpenFolderDialog(); + saveFolderDialog.InitialFolder = saveDirectoryBackup; + saveFolderDialog.Title = "Select Output Folder"; + if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) + { + if (File.Exists(Path.Combine(saveFolderDialog.Folder, $"{name}{exportListType.GetExtension()}"))) + { + var acceptOverride = MessageBox.Show("AssetMap already exist, Do you want to override it ?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (acceptOverride != DialogResult.Yes) + { + InvokeUpdate(miscToolStripMenuItem, true); + return; + } + } + saveDirectoryBackup = saveFolderDialog.Folder; + var toExportAssets = await Task.Run(() => AssetsHelper.BuildAssetMap(files, Studio.Game)); + AssetsHelper.ExportAssetsMap(toExportAssets, name, saveFolderDialog.Folder, exportListType); + } + } + InvokeUpdate(miscToolStripMenuItem, true); + } + #region FMOD private void FMODinit() { @@ -1694,7 +2048,7 @@ namespace AssetStudioGUI Application.Exit(); } - result = system.init(2, FMOD.INITFLAGS.NORMAL, IntPtr.Zero); + result = system.init(2, FMOD.INITFLAGS.NORMAL, nint.Zero); if (ERRCHECK(result)) { return; } result = system.getMasterSoundGroup(out masterSoundGroup); @@ -1952,10 +2306,10 @@ namespace AssetStudioGUI private void InitOpenTK() { ChangeGLSize(glControl.Size); - GL.ClearColor(Color4.Dimgray); + GL.ClearColor(Color4.Darkgray); pgmID = GL.CreateProgram(); - LoadShader("vs", ShaderType.VertexShader, pgmID, out var vsID); - LoadShader("fs", ShaderType.FragmentShader, pgmID, out var fsID); + LoadShader("vs", ShaderType.VertexShader, pgmID, out ShaderHandle vsID); + LoadShader("fs", ShaderType.FragmentShader, pgmID, out ShaderHandle fsID); GL.LinkProgram(pgmID); pgmColorID = GL.CreateProgram(); @@ -2011,7 +2365,7 @@ namespace AssetStudioGUI private static void CreateVBO(out BufferHandle vboAddress, Matrix4 data, int address) { GL.CreateBuffer(out vboAddress); - GL.UniformMatrix4f(address, false, data); + GL.UniformMatrix4f(address, false, in data); } private static void CreateEBO(out BufferHandle address, int[] data) @@ -2063,13 +2417,13 @@ namespace AssetStudioGUI } } - private void glControl1_Load(object sender, EventArgs e) + private void glControl_Load(object sender, EventArgs e) { InitOpenTK(); glControlLoaded = true; } - private void glControl1_Paint(object sender, PaintEventArgs e) + private void glControl_Paint(object sender, PaintEventArgs e) { glControl.MakeCurrent(); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); @@ -2079,9 +2433,9 @@ namespace AssetStudioGUI if (wireFrameMode == 0 || wireFrameMode == 2) { GL.UseProgram(shadeMode == 0 ? pgmID : pgmColorID); - GL.UniformMatrix4f(uniformModelMatrix, false, modelMatrixData); - GL.UniformMatrix4f(uniformViewMatrix, false, viewMatrixData); - GL.UniformMatrix4f(uniformProjMatrix, false, projMatrixData); + GL.UniformMatrix4f(uniformModelMatrix, false, in modelMatrixData); + GL.UniformMatrix4f(uniformViewMatrix, false, in viewMatrixData); + GL.UniformMatrix4f(uniformProjMatrix, false, in projMatrixData); GL.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill); GL.DrawElements(PrimitiveType.Triangles, indiceData.Length, DrawElementsType.UnsignedInt, 0); } @@ -2091,9 +2445,9 @@ namespace AssetStudioGUI GL.Enable(EnableCap.PolygonOffsetLine); GL.PolygonOffset(-1, -1); GL.UseProgram(pgmBlackID); - GL.UniformMatrix4f(uniformModelMatrix, false, modelMatrixData); - GL.UniformMatrix4f(uniformViewMatrix, false, viewMatrixData); - GL.UniformMatrix4f(uniformProjMatrix, false, projMatrixData); + GL.UniformMatrix4f(uniformModelMatrix, false, in modelMatrixData); + GL.UniformMatrix4f(uniformViewMatrix, false, in viewMatrixData); + GL.UniformMatrix4f(uniformProjMatrix, false, in projMatrixData); GL.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Line); GL.DrawElements(PrimitiveType.Triangles, indiceData.Length, DrawElementsType.UnsignedInt, 0); GL.Disable(EnableCap.PolygonOffsetLine); @@ -2103,130 +2457,7 @@ namespace AssetStudioGUI glControl.SwapBuffers(); } - private void tabControl2_SelectedIndexChanged(object sender, EventArgs e) - { - if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null) - { - dumpTextBox.Text = DumpAsset(lastSelectedItem.Asset); - } - } - - private void toolStripMenuItem15_Click(object sender, EventArgs e) - { - logger.ShowErrorMessage = toolStripMenuItem15.Checked; - } - - private async void buildCABMapToolStripMenuItem_Click(object sender, EventArgs e) - { - var openFolderDialog = new OpenFolderDialog(); - openFolderDialog.Title = $"Select {Studio.Game.Path} Folder"; - if (openFolderDialog.ShowDialog(this) == DialogResult.OK) - { - Logger.Info("scanning for files"); - var files = Directory.GetFiles(openFolderDialog.Folder, $"*{Studio.Game.Extension}", SearchOption.AllDirectories).ToList(); - Logger.Info(string.Format("found {0} files", files.Count())); - await Task.Run(() => CABManager.BuildMap(files, Studio.Game)); - } - } - - private async void buildAssetMapToolStripMenuItem_Click(object sender, EventArgs e) - { - var openFolderDialog = new OpenFolderDialog(); - openFolderDialog.Title = $"Select {Studio.Game.Path} Folder"; - if (openFolderDialog.ShowDialog(this) == DialogResult.OK) - { - Logger.Info("scanning for files"); - var files = Directory.GetFiles(openFolderDialog.Folder, $"*{Studio.Game.Extension}", SearchOption.AllDirectories).ToList(); - Logger.Info(string.Format("found {0} files", files.Count())); - - var saveFolderDialog = new OpenFolderDialog(); - saveFolderDialog.InitialFolder = saveDirectoryBackup; - saveFolderDialog.Title = "Select Output Folder"; - if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) - { - timer.Stop(); - saveDirectoryBackup = saveFolderDialog.Folder; - List toExportAssets = await Task.Run(() => BuildAssetMap(files)); - ExportAssetsMap(saveFolderDialog.Folder, toExportAssets, ExportListType.XML); - } - } - } - - private async void toolStripMenuItem16_DropDownOpening(object sender, EventArgs e) - { - if (specifyAIVersion.Enabled && await AIVersionManager.FetchVersions()) - { - UpdateVersionList(); - } - } - - private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e) - { - if (specifyAIVersion.SelectedIndex == 0) - { - return; - } - optionsToolStripMenuItem.DropDown.Visible = false; - var version = specifyAIVersion.SelectedItem.ToString(); - - if (version.Contains(" ")) - { - version = version.Split(' ')[0]; - } - - Logger.Info($"Loading AI v{version}"); - SpecifyAIVersionUpdate(false); - var path = await AIVersionManager.FetchAI(version); - await Task.Run(() => ResourceIndex.FromFile(path)); - UpdateVersionList(); - SpecifyAIVersionUpdate(true); - } - - private void UpdateVersionList() - { - var selectedIndex = specifyAIVersion.SelectedIndex; - specifyAIVersion.Items.Clear(); - specifyAIVersion.Items.Add("None"); - - var versions = AIVersionManager.GetVersions(); - foreach (var version in versions) - { - specifyAIVersion.Items.Add(version.Item1 + (version.Item2 ? " (cached)" : "")); - } - - specifyAIVersion.SelectedIndexChanged -= new EventHandler(toolStripComboBox1_SelectedIndexChanged); - specifyAIVersion.SelectedIndex = selectedIndex; - specifyAIVersion.SelectedIndexChanged += new EventHandler(toolStripComboBox1_SelectedIndexChanged); - } - - private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e) - { - optionsToolStripMenuItem.DropDown.Visible = false; - Properties.Settings.Default.selectedGame = specifyGame.SelectedIndex; - Properties.Settings.Default.Save(); - - Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame); - Logger.Info($"Target Game is {Studio.Game.Name}"); - - ResetForm(); - assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text; - assetsManager.Game = Studio.Game; - CABManager.LoadMap(Studio.Game); - } - - private void SpecifyAIVersionUpdate(bool value) - { - if (InvokeRequired) - { - BeginInvoke(new Action(() => { specifyAIVersion.Enabled = value; })); - } - else - { - specifyAIVersion.Enabled = value; - } - } - - private void glControl1_MouseWheel(object sender, MouseEventArgs e) + private void glControl_MouseWheel(object sender, MouseEventArgs e) { if (glControl.Visible) { @@ -2235,7 +2466,7 @@ namespace AssetStudioGUI } } - private void glControl1_MouseDown(object sender, MouseEventArgs e) + private void glControl_MouseDown(object sender, MouseEventArgs e) { mdx = e.X; mdy = e.Y; @@ -2249,7 +2480,7 @@ namespace AssetStudioGUI } } - private void glControl1_MouseMove(object sender, MouseEventArgs e) + private void glControl_MouseMove(object sender, MouseEventArgs e) { if (lmdown || rmdown) { @@ -2274,7 +2505,7 @@ namespace AssetStudioGUI } } - private void glControl1_MouseUp(object sender, MouseEventArgs e) + private void glControl_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { diff --git a/AssetStudioGUI/AssetStudioGUIForm.resx b/AssetStudioGUI/AssetStudioGUIForm.resx index 03b8180..ee3dd05 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.resx +++ b/AssetStudioGUI/AssetStudioGUIForm.resx @@ -1,64 +1,4 @@ - - - + diff --git a/AssetStudioGUI/CNUnityForm.Designer.cs b/AssetStudioGUI/CNUnityForm.Designer.cs new file mode 100644 index 0000000..c851456 --- /dev/null +++ b/AssetStudioGUI/CNUnityForm.Designer.cs @@ -0,0 +1,123 @@ +namespace AssetStudioGUI +{ + partial class CNUnityForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.specifyCNUnityList = new System.Windows.Forms.DataGridView(); + this.NameField = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.KeyField = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Cancel = new System.Windows.Forms.Button(); + this.OKbutton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.specifyCNUnityList)).BeginInit(); + this.SuspendLayout(); + // + // specifyCNUnityList + // + this.specifyCNUnityList.AllowUserToResizeColumns = false; + this.specifyCNUnityList.AllowUserToResizeRows = false; + this.specifyCNUnityList.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText; + this.specifyCNUnityList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.specifyCNUnityList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.NameField, + this.KeyField}); + this.specifyCNUnityList.Location = new System.Drawing.Point(12, 12); + this.specifyCNUnityList.MultiSelect = false; + this.specifyCNUnityList.Name = "specifyCNUnityList"; + this.specifyCNUnityList.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; + this.specifyCNUnityList.RowTemplate.Height = 25; + this.specifyCNUnityList.Size = new System.Drawing.Size(332, 171); + this.specifyCNUnityList.TabIndex = 0; + // + // NameField + // + this.NameField.HeaderText = "Name"; + this.NameField.Name = "NameField"; + this.NameField.Width = 140; + // + // KeyField + // + this.KeyField.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.KeyField.HeaderText = "Key"; + this.KeyField.Name = "KeyField"; + // + // Cancel + // + this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Cancel.Location = new System.Drawing.Point(255, 190); + this.Cancel.Margin = new System.Windows.Forms.Padding(4); + this.Cancel.Name = "Cancel"; + this.Cancel.Size = new System.Drawing.Size(88, 26); + this.Cancel.TabIndex = 9; + this.Cancel.Text = "Cancel"; + this.Cancel.UseVisualStyleBackColor = true; + this.Cancel.Click += new System.EventHandler(this.Cancel_Click); + // + // OKbutton + // + this.OKbutton.Location = new System.Drawing.Point(159, 190); + this.OKbutton.Margin = new System.Windows.Forms.Padding(4); + this.OKbutton.Name = "OKbutton"; + this.OKbutton.Size = new System.Drawing.Size(88, 26); + this.OKbutton.TabIndex = 8; + this.OKbutton.Text = "OK"; + this.OKbutton.UseVisualStyleBackColor = true; + this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click); + // + // CNUnityForm + // + this.AcceptButton = this.OKbutton; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.Cancel; + this.ClientSize = new System.Drawing.Size(356, 229); + this.Controls.Add(this.Cancel); + this.Controls.Add(this.OKbutton); + this.Controls.Add(this.specifyCNUnityList); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CNUnityForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "CNUnityForm"; + this.TopMost = true; + ((System.ComponentModel.ISupportInitialize)(this.specifyCNUnityList)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.DataGridView specifyCNUnityList; + private System.Windows.Forms.Button Cancel; + private System.Windows.Forms.Button OKbutton; + private System.Windows.Forms.DataGridViewTextBoxColumn NameField; + private System.Windows.Forms.DataGridViewTextBoxColumn KeyField; + } +} \ No newline at end of file diff --git a/AssetStudioGUI/CNUnityForm.cs b/AssetStudioGUI/CNUnityForm.cs new file mode 100644 index 0000000..5d00edc --- /dev/null +++ b/AssetStudioGUI/CNUnityForm.cs @@ -0,0 +1,83 @@ +using System; +using System.Windows.Forms; +using System.Collections.Generic; +using AssetStudio; +using System.Linq; + +namespace AssetStudioGUI +{ + public partial class CNUnityForm : Form + { + public CNUnityForm() + { + InitializeComponent(); + + var keys = CNUnityKeyManager.GetEntries(); + + for (int i = 0; i < keys.Length; i++) + { + var key = keys[i]; + var rowIdx = specifyCNUnityList.Rows.Add(); + + specifyCNUnityList.Rows[rowIdx].Cells["NameField"].Value = key.Name; + specifyCNUnityList.Rows[rowIdx].Cells["KeyField"].Value = key.Key; + } + + var index = Properties.Settings.Default.selectedCNUnityKey; + if (index >= specifyCNUnityList.RowCount) + { + index = 0; + } + specifyCNUnityList.CurrentCell = specifyCNUnityList.Rows[index].Cells[0]; + } + + private void OKbutton_Click(object sender, EventArgs e) + { + var keys = new List(); + for (int i = specifyCNUnityList.Rows.Count - 1; i >= 0; i--) + { + var row = specifyCNUnityList.Rows[i]; + var name = row.Cells["NameField"].Value as string; + var key = row.Cells["KeyField"].Value as string; + + if (!(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key))) + { + var cnunity = new CNUnity.Entry(name, key); + + if (cnunity.Validate()) + { + keys.Add(cnunity); + continue; + } + } + + if (specifyCNUnityList.CurrentCell.RowIndex == row.Index) + { + var previousRow = specifyCNUnityList.Rows.Cast().ElementAtOrDefault(i - 1); + if (previousRow != null) + { + specifyCNUnityList.CurrentCell = previousRow.Cells[0]; + } + } + if (i != specifyCNUnityList.RowCount - 1) + { + specifyCNUnityList.Rows.RemoveAt(i); + } + } + CNUnityKeyManager.SaveEntries(keys.Reverse().ToList()); + CNUnityKeyManager.SetKey(specifyCNUnityList.CurrentRow.Index); + + Properties.Settings.Default.selectedCNUnityKey = specifyCNUnityList.CurrentRow.Index; + Properties.Settings.Default.Save(); + + DialogResult = DialogResult.OK; + Close(); + } + + private void Cancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/AssetStudioGUI/CNUnityForm.resx b/AssetStudioGUI/CNUnityForm.resx new file mode 100644 index 0000000..da13c3e --- /dev/null +++ b/AssetStudioGUI/CNUnityForm.resx @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + True + + \ No newline at end of file diff --git a/AssetStudioGUI/Components/OpenFolderDialog.cs b/AssetStudioGUI/Components/OpenFolderDialog.cs index 7612a6e..ff80a9c 100644 --- a/AssetStudioGUI/Components/OpenFolderDialog.cs +++ b/AssetStudioGUI/Components/OpenFolderDialog.cs @@ -34,7 +34,7 @@ namespace AssetStudioGUI if (!string.IsNullOrEmpty(InitialFolder)) { var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem - if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK) + if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, nint.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK) { frm.SetFolder(directoryShellItem); } @@ -42,7 +42,7 @@ namespace AssetStudioGUI if (!string.IsNullOrEmpty(DefaultFolder)) { var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem - if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK) + if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, nint.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK) { frm.SetDefaultFolder(directoryShellItem); } @@ -54,7 +54,7 @@ namespace AssetStudioGUI { if (shellItem.GetDisplayName(NativeMethods.SIGDN_FILESYSPATH, out var pszString) == NativeMethods.S_OK) { - if (pszString != IntPtr.Zero) + if (pszString != nint.Zero) { try { @@ -127,11 +127,11 @@ namespace AssetStudioGUI { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [PreserveSig()] - uint Show([In, Optional] IntPtr hwndOwner); //IModalWindow + uint Show([In, Optional] nint hwndOwner); //IModalWindow [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - uint SetFileTypes([In] uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr rgFilterSpec); + uint SetFileTypes([In] uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray)] nint rgFilterSpec); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] uint SetFileTypeIndex([In] uint iFileType); @@ -140,7 +140,7 @@ namespace AssetStudioGUI uint GetFileTypeIndex(out uint piFileType); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - uint Advise([In, MarshalAs(UnmanagedType.Interface)] IntPtr pfde, out uint pdwCookie); + uint Advise([In, MarshalAs(UnmanagedType.Interface)] nint pfde, out uint pdwCookie); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] uint Unadvise([In] uint dwCookie); @@ -197,7 +197,7 @@ namespace AssetStudioGUI uint ClearClientData(); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - uint SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter); + uint SetFilter([MarshalAs(UnmanagedType.Interface)] nint pFilter); } @@ -205,13 +205,13 @@ namespace AssetStudioGUI internal interface IShellItem { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - uint BindToHandler([In] IntPtr pbc, [In] ref Guid rbhid, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IntPtr ppvOut); + uint BindToHandler([In] nint pbc, [In] ref Guid rbhid, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out nint ppvOut); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] uint GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - uint GetDisplayName([In] uint sigdnName, out IntPtr ppszName); + uint GetDisplayName([In] uint sigdnName, out nint ppszName); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] uint GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs); @@ -224,6 +224,6 @@ namespace AssetStudioGUI [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv); + internal static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, nint pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv); } } \ No newline at end of file diff --git a/AssetStudioGUI/ExportOptions.Designer.cs b/AssetStudioGUI/ExportOptions.Designer.cs index 62fd8dc..f620b7a 100644 --- a/AssetStudioGUI/ExportOptions.Designer.cs +++ b/AssetStudioGUI/ExportOptions.Designer.cs @@ -32,11 +32,8 @@ this.OKbutton = new System.Windows.Forms.Button(); this.Cancel = new System.Windows.Forms.Button(); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.disableShader = new System.Windows.Forms.CheckBox(); - this.ignoreController = new System.Windows.Forms.CheckBox(); - this.disableRndrr = new System.Windows.Forms.CheckBox(); - this.exportIndexObject = new System.Windows.Forms.CheckBox(); - this.exportAssetBundle = new System.Windows.Forms.CheckBox(); + this.skipRenderer = new System.Windows.Forms.CheckBox(); + this.exportMiHoYoBinData = new System.Windows.Forms.CheckBox(); this.openAfterExport = new System.Windows.Forms.CheckBox(); this.restoreExtensionName = new System.Windows.Forms.CheckBox(); this.assetGroupOptions = new System.Windows.Forms.ComboBox(); @@ -48,6 +45,7 @@ this.topng = new System.Windows.Forms.RadioButton(); this.tobmp = new System.Windows.Forms.RadioButton(); this.converttexture = new System.Windows.Forms.CheckBox(); + this.collectAnimations = new System.Windows.Forms.CheckBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.exportAllUvsAsDiffuseMaps = new System.Windows.Forms.CheckBox(); this.exportBlendShape = new System.Windows.Forms.CheckBox(); @@ -68,9 +66,10 @@ this.eulerFilter = new System.Windows.Forms.CheckBox(); this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components); this.groupBox3 = new System.Windows.Forms.GroupBox(); - this.enableXor = new System.Windows.Forms.CheckBox(); + this.encrypted = new System.Windows.Forms.CheckBox(); this.key = new System.Windows.Forms.NumericUpDown(); this.label7 = new System.Windows.Forms.Label(); + this.keyToolTip = new System.Windows.Forms.ToolTip(this.components); this.groupBox1.SuspendLayout(); this.panel1.SuspendLayout(); this.groupBox2.SuspendLayout(); @@ -83,9 +82,10 @@ // // OKbutton // - this.OKbutton.Location = new System.Drawing.Point(318, 380); + this.OKbutton.Location = new System.Drawing.Point(371, 439); + this.OKbutton.Margin = new System.Windows.Forms.Padding(4); this.OKbutton.Name = "OKbutton"; - this.OKbutton.Size = new System.Drawing.Size(75, 23); + this.OKbutton.Size = new System.Drawing.Size(88, 26); this.OKbutton.TabIndex = 6; this.OKbutton.Text = "OK"; this.OKbutton.UseVisualStyleBackColor = true; @@ -94,9 +94,10 @@ // Cancel // this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.Cancel.Location = new System.Drawing.Point(399, 380); + this.Cancel.Location = new System.Drawing.Point(465, 439); + this.Cancel.Margin = new System.Windows.Forms.Padding(4); this.Cancel.Name = "Cancel"; - this.Cancel.Size = new System.Drawing.Size(75, 23); + this.Cancel.Size = new System.Drawing.Size(88, 26); this.Cancel.TabIndex = 7; this.Cancel.Text = "Cancel"; this.Cancel.UseVisualStyleBackColor = true; @@ -105,11 +106,8 @@ // groupBox1 // this.groupBox1.AutoSize = true; - this.groupBox1.Controls.Add(this.disableShader); - this.groupBox1.Controls.Add(this.ignoreController); - this.groupBox1.Controls.Add(this.disableRndrr); - this.groupBox1.Controls.Add(this.exportIndexObject); - this.groupBox1.Controls.Add(this.exportAssetBundle); + this.groupBox1.Controls.Add(this.skipRenderer); + this.groupBox1.Controls.Add(this.exportMiHoYoBinData); this.groupBox1.Controls.Add(this.openAfterExport); this.groupBox1.Controls.Add(this.restoreExtensionName); this.groupBox1.Controls.Add(this.assetGroupOptions); @@ -117,77 +115,48 @@ this.groupBox1.Controls.Add(this.convertAudio); this.groupBox1.Controls.Add(this.panel1); this.groupBox1.Controls.Add(this.converttexture); - this.groupBox1.Location = new System.Drawing.Point(12, 13); + this.groupBox1.Location = new System.Drawing.Point(14, 15); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(232, 277); + this.groupBox1.Padding = new System.Windows.Forms.Padding(4); + this.groupBox1.Size = new System.Drawing.Size(271, 293); this.groupBox1.TabIndex = 9; this.groupBox1.TabStop = false; this.groupBox1.Text = "Export"; // - // disableShader + // skipRenderer // - this.disableShader.AutoSize = true; - this.disableShader.Location = new System.Drawing.Point(97, 219); - this.disableShader.Name = "disableShader"; - this.disableShader.Size = new System.Drawing.Size(98, 17); - this.disableShader.TabIndex = 22; - this.disableShader.Text = "Disable Shader"; - this.disableShader.UseVisualStyleBackColor = true; + this.skipRenderer.AutoSize = true; + this.skipRenderer.Location = new System.Drawing.Point(7, 226); + this.skipRenderer.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.skipRenderer.Name = "skipRenderer"; + this.skipRenderer.Size = new System.Drawing.Size(98, 19); + this.skipRenderer.TabIndex = 23; + this.skipRenderer.Text = "Skip Renderer"; + this.skipRenderer.UseVisualStyleBackColor = true; // - // ignoreController + // exportMiHoYoBinData // - this.ignoreController.AutoSize = true; - this.ignoreController.Checked = true; - this.ignoreController.CheckState = System.Windows.Forms.CheckState.Checked; - this.ignoreController.Location = new System.Drawing.Point(6, 241); - this.ignoreController.Name = "ignoreController"; - this.ignoreController.Size = new System.Drawing.Size(152, 17); - this.ignoreController.TabIndex = 21; - this.ignoreController.Text = "Ignore Controller Animation"; - this.ignoreController.UseVisualStyleBackColor = true; - // - // disableRndrr - // - this.disableRndrr.AutoSize = true; - this.disableRndrr.Location = new System.Drawing.Point(97, 196); - this.disableRndrr.Name = "disableRndrr"; - this.disableRndrr.Size = new System.Drawing.Size(113, 17); - this.disableRndrr.TabIndex = 13; - this.disableRndrr.Text = "Disable Renderers"; - this.disableRndrr.UseVisualStyleBackColor = true; - // - // exportIndexObject - // - this.exportIndexObject.AutoSize = true; - this.exportIndexObject.Checked = true; - this.exportIndexObject.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportIndexObject.Location = new System.Drawing.Point(6, 219); - this.exportIndexObject.Name = "exportIndexObject"; - this.exportIndexObject.Size = new System.Drawing.Size(83, 17); - this.exportIndexObject.TabIndex = 12; - this.exportIndexObject.Text = "IndexObject"; - this.exportIndexObject.UseVisualStyleBackColor = true; - // - // exportAssetBundle - // - this.exportAssetBundle.AutoSize = true; - this.exportAssetBundle.Checked = true; - this.exportAssetBundle.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportAssetBundle.Location = new System.Drawing.Point(6, 196); - this.exportAssetBundle.Name = "exportAssetBundle"; - this.exportAssetBundle.Size = new System.Drawing.Size(85, 17); - this.exportAssetBundle.TabIndex = 11; - this.exportAssetBundle.Text = "AssetBundle"; - this.exportAssetBundle.UseVisualStyleBackColor = true; + this.exportMiHoYoBinData.AutoSize = true; + this.exportMiHoYoBinData.Checked = true; + this.exportMiHoYoBinData.CheckState = System.Windows.Forms.CheckState.Checked; + this.exportMiHoYoBinData.Location = new System.Drawing.Point(7, 251); + this.exportMiHoYoBinData.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.exportMiHoYoBinData.Name = "exportMiHoYoBinData"; + this.exportMiHoYoBinData.Size = new System.Drawing.Size(147, 19); + this.exportMiHoYoBinData.TabIndex = 22; + this.exportMiHoYoBinData.Text = "Export MiHoYoBinData"; + this.exportMiHoYoBinData.UseVisualStyleBackColor = true; // // openAfterExport // this.openAfterExport.AutoSize = true; this.openAfterExport.Checked = true; this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked; - this.openAfterExport.Location = new System.Drawing.Point(6, 173); + this.openAfterExport.Location = new System.Drawing.Point(7, 200); + this.openAfterExport.Margin = new System.Windows.Forms.Padding(4); this.openAfterExport.Name = "openAfterExport"; - this.openAfterExport.Size = new System.Drawing.Size(137, 17); + this.openAfterExport.Size = new System.Drawing.Size(153, 19); this.openAfterExport.TabIndex = 10; this.openAfterExport.Text = "Open folder after export"; this.openAfterExport.UseVisualStyleBackColor = true; @@ -197,9 +166,10 @@ this.restoreExtensionName.AutoSize = true; this.restoreExtensionName.Checked = true; this.restoreExtensionName.CheckState = System.Windows.Forms.CheckState.Checked; - this.restoreExtensionName.Location = new System.Drawing.Point(6, 63); + this.restoreExtensionName.Location = new System.Drawing.Point(7, 72); + this.restoreExtensionName.Margin = new System.Windows.Forms.Padding(4); this.restoreExtensionName.Name = "restoreExtensionName"; - this.restoreExtensionName.Size = new System.Drawing.Size(190, 17); + this.restoreExtensionName.Size = new System.Drawing.Size(204, 19); this.restoreExtensionName.TabIndex = 9; this.restoreExtensionName.Text = "Restore TextAsset extension name"; this.restoreExtensionName.UseVisualStyleBackColor = true; @@ -213,17 +183,19 @@ "container path", "source file name", "do not group"}); - this.assetGroupOptions.Location = new System.Drawing.Point(6, 35); + this.assetGroupOptions.Location = new System.Drawing.Point(7, 40); + this.assetGroupOptions.Margin = new System.Windows.Forms.Padding(4); this.assetGroupOptions.Name = "assetGroupOptions"; - this.assetGroupOptions.Size = new System.Drawing.Size(149, 21); + this.assetGroupOptions.Size = new System.Drawing.Size(173, 23); this.assetGroupOptions.TabIndex = 8; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(6, 18); + this.label6.Location = new System.Drawing.Point(7, 21); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(127, 13); + this.label6.Size = new System.Drawing.Size(140, 15); this.label6.TabIndex = 7; this.label6.Text = "Group exported assets by"; // @@ -232,9 +204,10 @@ this.convertAudio.AutoSize = true; this.convertAudio.Checked = true; this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked; - this.convertAudio.Location = new System.Drawing.Point(6, 150); + this.convertAudio.Location = new System.Drawing.Point(7, 172); + this.convertAudio.Margin = new System.Windows.Forms.Padding(4); this.convertAudio.Name = "convertAudio"; - this.convertAudio.Size = new System.Drawing.Size(179, 17); + this.convertAudio.Size = new System.Drawing.Size(200, 19); this.convertAudio.TabIndex = 6; this.convertAudio.Text = "Convert AudioClip to WAV(PCM)"; this.convertAudio.UseVisualStyleBackColor = true; @@ -245,17 +218,19 @@ this.panel1.Controls.Add(this.tojpg); this.panel1.Controls.Add(this.topng); this.panel1.Controls.Add(this.tobmp); - this.panel1.Location = new System.Drawing.Point(20, 111); + this.panel1.Location = new System.Drawing.Point(23, 128); + this.panel1.Margin = new System.Windows.Forms.Padding(4); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(202, 32); + this.panel1.Size = new System.Drawing.Size(236, 38); this.panel1.TabIndex = 5; // // totga // this.totga.AutoSize = true; - this.totga.Location = new System.Drawing.Point(150, 6); + this.totga.Location = new System.Drawing.Point(175, 8); + this.totga.Margin = new System.Windows.Forms.Padding(4); this.totga.Name = "totga"; - this.totga.Size = new System.Drawing.Size(44, 17); + this.totga.Size = new System.Drawing.Size(43, 19); this.totga.TabIndex = 2; this.totga.Text = "Tga"; this.totga.UseVisualStyleBackColor = true; @@ -263,9 +238,10 @@ // tojpg // this.tojpg.AutoSize = true; - this.tojpg.Location = new System.Drawing.Point(97, 6); + this.tojpg.Location = new System.Drawing.Point(113, 8); + this.tojpg.Margin = new System.Windows.Forms.Padding(4); this.tojpg.Name = "tojpg"; - this.tojpg.Size = new System.Drawing.Size(48, 17); + this.tojpg.Size = new System.Drawing.Size(49, 19); this.tojpg.TabIndex = 4; this.tojpg.Text = "Jpeg"; this.tojpg.UseVisualStyleBackColor = true; @@ -274,9 +250,10 @@ // this.topng.AutoSize = true; this.topng.Checked = true; - this.topng.Location = new System.Drawing.Point(50, 6); + this.topng.Location = new System.Drawing.Point(58, 8); + this.topng.Margin = new System.Windows.Forms.Padding(4); this.topng.Name = "topng"; - this.topng.Size = new System.Drawing.Size(44, 17); + this.topng.Size = new System.Drawing.Size(46, 19); this.topng.TabIndex = 3; this.topng.TabStop = true; this.topng.Text = "Png"; @@ -285,9 +262,10 @@ // tobmp // this.tobmp.AutoSize = true; - this.tobmp.Location = new System.Drawing.Point(3, 6); + this.tobmp.Location = new System.Drawing.Point(4, 8); + this.tobmp.Margin = new System.Windows.Forms.Padding(4); this.tobmp.Name = "tobmp"; - this.tobmp.Size = new System.Drawing.Size(46, 17); + this.tobmp.Size = new System.Drawing.Size(50, 19); this.tobmp.TabIndex = 2; this.tobmp.Text = "Bmp"; this.tobmp.UseVisualStyleBackColor = true; @@ -297,16 +275,31 @@ this.converttexture.AutoSize = true; this.converttexture.Checked = true; this.converttexture.CheckState = System.Windows.Forms.CheckState.Checked; - this.converttexture.Location = new System.Drawing.Point(6, 87); + this.converttexture.Location = new System.Drawing.Point(7, 100); + this.converttexture.Margin = new System.Windows.Forms.Padding(4); this.converttexture.Name = "converttexture"; - this.converttexture.Size = new System.Drawing.Size(116, 17); + this.converttexture.Size = new System.Drawing.Size(123, 19); this.converttexture.TabIndex = 1; this.converttexture.Text = "Convert Texture2D"; this.converttexture.UseVisualStyleBackColor = true; // + // collectAnimations + // + this.collectAnimations.AutoSize = true; + this.collectAnimations.Checked = true; + this.collectAnimations.CheckState = System.Windows.Forms.CheckState.Checked; + this.collectAnimations.Location = new System.Drawing.Point(8, 122); + this.collectAnimations.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.collectAnimations.Name = "collectAnimations"; + this.collectAnimations.Size = new System.Drawing.Size(125, 19); + this.collectAnimations.TabIndex = 24; + this.collectAnimations.Text = "Collect animations"; + this.collectAnimations.UseVisualStyleBackColor = true; + // // groupBox2 // this.groupBox2.AutoSize = true; + this.groupBox2.Controls.Add(this.collectAnimations); this.groupBox2.Controls.Add(this.exportAllUvsAsDiffuseMaps); this.groupBox2.Controls.Add(this.exportBlendShape); this.groupBox2.Controls.Add(this.exportAnimations); @@ -324,9 +317,11 @@ this.groupBox2.Controls.Add(this.castToBone); this.groupBox2.Controls.Add(this.exportAllNodes); this.groupBox2.Controls.Add(this.eulerFilter); - this.groupBox2.Location = new System.Drawing.Point(250, 13); + this.groupBox2.Location = new System.Drawing.Point(292, 15); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(224, 362); + this.groupBox2.Padding = new System.Windows.Forms.Padding(4); + this.groupBox2.Size = new System.Drawing.Size(261, 419); this.groupBox2.TabIndex = 11; this.groupBox2.TabStop = false; this.groupBox2.Text = "Fbx"; @@ -335,9 +330,10 @@ // this.exportAllUvsAsDiffuseMaps.AccessibleDescription = ""; this.exportAllUvsAsDiffuseMaps.AutoSize = true; - this.exportAllUvsAsDiffuseMaps.Location = new System.Drawing.Point(6, 185); + this.exportAllUvsAsDiffuseMaps.Location = new System.Drawing.Point(8, 226); + this.exportAllUvsAsDiffuseMaps.Margin = new System.Windows.Forms.Padding(4); this.exportAllUvsAsDiffuseMaps.Name = "exportAllUvsAsDiffuseMaps"; - this.exportAllUvsAsDiffuseMaps.Size = new System.Drawing.Size(168, 17); + this.exportAllUvsAsDiffuseMaps.Size = new System.Drawing.Size(183, 19); this.exportAllUvsAsDiffuseMaps.TabIndex = 23; this.exportAllUvsAsDiffuseMaps.Text = "Export all UVs as diffuse maps"; this.exportUvsTooltip.SetToolTip(this.exportAllUvsAsDiffuseMaps, "Unchecked: UV1 exported as normal map. Check this if your export is missing a UV " + @@ -349,9 +345,10 @@ this.exportBlendShape.AutoSize = true; this.exportBlendShape.Checked = true; this.exportBlendShape.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportBlendShape.Location = new System.Drawing.Point(6, 138); + this.exportBlendShape.Location = new System.Drawing.Point(8, 172); + this.exportBlendShape.Margin = new System.Windows.Forms.Padding(4); this.exportBlendShape.Name = "exportBlendShape"; - this.exportBlendShape.Size = new System.Drawing.Size(114, 17); + this.exportBlendShape.Size = new System.Drawing.Size(124, 19); this.exportBlendShape.TabIndex = 22; this.exportBlendShape.Text = "Export blendshape"; this.exportBlendShape.UseVisualStyleBackColor = true; @@ -361,9 +358,10 @@ this.exportAnimations.AutoSize = true; this.exportAnimations.Checked = true; this.exportAnimations.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportAnimations.Location = new System.Drawing.Point(6, 114); + this.exportAnimations.Location = new System.Drawing.Point(8, 147); + this.exportAnimations.Margin = new System.Windows.Forms.Padding(4); this.exportAnimations.Name = "exportAnimations"; - this.exportAnimations.Size = new System.Drawing.Size(109, 17); + this.exportAnimations.Size = new System.Drawing.Size(122, 19); this.exportAnimations.TabIndex = 21; this.exportAnimations.Text = "Export animations"; this.exportAnimations.UseVisualStyleBackColor = true; @@ -376,9 +374,10 @@ 0, 0, 131072}); - this.scaleFactor.Location = new System.Drawing.Point(83, 243); + this.scaleFactor.Location = new System.Drawing.Point(98, 292); + this.scaleFactor.Margin = new System.Windows.Forms.Padding(4); this.scaleFactor.Name = "scaleFactor"; - this.scaleFactor.Size = new System.Drawing.Size(60, 20); + this.scaleFactor.Size = new System.Drawing.Size(70, 23); this.scaleFactor.TabIndex = 20; this.scaleFactor.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.scaleFactor.Value = new decimal(new int[] { @@ -390,9 +389,10 @@ // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(6, 245); + this.label5.Location = new System.Drawing.Point(8, 294); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(64, 13); + this.label5.Size = new System.Drawing.Size(67, 15); this.label5.TabIndex = 19; this.label5.Text = "ScaleFactor"; // @@ -403,17 +403,19 @@ this.fbxFormat.Items.AddRange(new object[] { "Binary", "Ascii"}); - this.fbxFormat.Location = new System.Drawing.Point(77, 275); + this.fbxFormat.Location = new System.Drawing.Point(91, 330); + this.fbxFormat.Margin = new System.Windows.Forms.Padding(4); this.fbxFormat.Name = "fbxFormat"; - this.fbxFormat.Size = new System.Drawing.Size(61, 21); + this.fbxFormat.Size = new System.Drawing.Size(70, 23); this.fbxFormat.TabIndex = 18; // // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(6, 280); + this.label4.Location = new System.Drawing.Point(8, 334); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(59, 13); + this.label4.Size = new System.Drawing.Size(65, 15); this.label4.TabIndex = 17; this.label4.Text = "FBXFormat"; // @@ -428,25 +430,28 @@ "7.3", "7.4", "7.5"}); - this.fbxVersion.Location = new System.Drawing.Point(77, 308); + this.fbxVersion.Location = new System.Drawing.Point(91, 367); + this.fbxVersion.Margin = new System.Windows.Forms.Padding(4); this.fbxVersion.Name = "fbxVersion"; - this.fbxVersion.Size = new System.Drawing.Size(47, 21); + this.fbxVersion.Size = new System.Drawing.Size(54, 23); this.fbxVersion.TabIndex = 16; // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(6, 311); + this.label3.Location = new System.Drawing.Point(8, 371); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(62, 13); + this.label3.Size = new System.Drawing.Size(65, 15); this.label3.TabIndex = 15; this.label3.Text = "FBXVersion"; // // boneSize // - this.boneSize.Location = new System.Drawing.Point(65, 213); + this.boneSize.Location = new System.Drawing.Point(77, 258); + this.boneSize.Margin = new System.Windows.Forms.Padding(4); this.boneSize.Name = "boneSize"; - this.boneSize.Size = new System.Drawing.Size(46, 20); + this.boneSize.Size = new System.Drawing.Size(54, 23); this.boneSize.TabIndex = 11; this.boneSize.Value = new decimal(new int[] { 10, @@ -457,9 +462,10 @@ // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(6, 216); + this.label2.Location = new System.Drawing.Point(8, 260); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(52, 13); + this.label2.Size = new System.Drawing.Size(54, 15); this.label2.TabIndex = 10; this.label2.Text = "BoneSize"; // @@ -468,9 +474,10 @@ this.exportSkins.AutoSize = true; this.exportSkins.Checked = true; this.exportSkins.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportSkins.Location = new System.Drawing.Point(6, 90); + this.exportSkins.Location = new System.Drawing.Point(8, 96); + this.exportSkins.Margin = new System.Windows.Forms.Padding(4); this.exportSkins.Name = "exportSkins"; - this.exportSkins.Size = new System.Drawing.Size(83, 17); + this.exportSkins.Size = new System.Drawing.Size(89, 19); this.exportSkins.TabIndex = 8; this.exportSkins.Text = "Export skins"; this.exportSkins.UseVisualStyleBackColor = true; @@ -478,9 +485,10 @@ // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(26, 42); + this.label1.Location = new System.Drawing.Point(31, 41); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(72, 13); + this.label1.Size = new System.Drawing.Size(81, 15); this.label1.TabIndex = 7; this.label1.Text = "FilterPrecision"; // @@ -492,9 +500,10 @@ 0, 0, 131072}); - this.filterPrecision.Location = new System.Drawing.Point(127, 40); + this.filterPrecision.Location = new System.Drawing.Point(149, 38); + this.filterPrecision.Margin = new System.Windows.Forms.Padding(4); this.filterPrecision.Name = "filterPrecision"; - this.filterPrecision.Size = new System.Drawing.Size(51, 20); + this.filterPrecision.Size = new System.Drawing.Size(59, 23); this.filterPrecision.TabIndex = 6; this.filterPrecision.Value = new decimal(new int[] { 25, @@ -505,9 +514,10 @@ // castToBone // this.castToBone.AutoSize = true; - this.castToBone.Location = new System.Drawing.Point(6, 161); + this.castToBone.Location = new System.Drawing.Point(8, 198); + this.castToBone.Margin = new System.Windows.Forms.Padding(4); this.castToBone.Name = "castToBone"; - this.castToBone.Size = new System.Drawing.Size(131, 17); + this.castToBone.Size = new System.Drawing.Size(143, 19); this.castToBone.TabIndex = 5; this.castToBone.Text = "All nodes cast to bone"; this.castToBone.UseVisualStyleBackColor = true; @@ -517,9 +527,10 @@ this.exportAllNodes.AutoSize = true; this.exportAllNodes.Checked = true; this.exportAllNodes.CheckState = System.Windows.Forms.CheckState.Checked; - this.exportAllNodes.Location = new System.Drawing.Point(6, 66); + this.exportAllNodes.Location = new System.Drawing.Point(8, 68); + this.exportAllNodes.Margin = new System.Windows.Forms.Padding(4); this.exportAllNodes.Name = "exportAllNodes"; - this.exportAllNodes.Size = new System.Drawing.Size(101, 17); + this.exportAllNodes.Size = new System.Drawing.Size(110, 19); this.exportAllNodes.TabIndex = 4; this.exportAllNodes.Text = "Export all nodes"; this.exportAllNodes.UseVisualStyleBackColor = true; @@ -529,9 +540,10 @@ this.eulerFilter.AutoSize = true; this.eulerFilter.Checked = true; this.eulerFilter.CheckState = System.Windows.Forms.CheckState.Checked; - this.eulerFilter.Location = new System.Drawing.Point(6, 22); + this.eulerFilter.Location = new System.Drawing.Point(8, 17); + this.eulerFilter.Margin = new System.Windows.Forms.Padding(4); this.eulerFilter.Name = "eulerFilter"; - this.eulerFilter.Size = new System.Drawing.Size(72, 17); + this.eulerFilter.Size = new System.Drawing.Size(78, 19); this.eulerFilter.TabIndex = 3; this.eulerFilter.Text = "EulerFilter"; this.eulerFilter.UseVisualStyleBackColor = true; @@ -539,62 +551,69 @@ // groupBox3 // this.groupBox3.AutoSize = true; - this.groupBox3.Controls.Add(this.enableXor); + this.groupBox3.Controls.Add(this.encrypted); this.groupBox3.Controls.Add(this.key); this.groupBox3.Controls.Add(this.label7); - this.groupBox3.Location = new System.Drawing.Point(12, 296); + this.groupBox3.Location = new System.Drawing.Point(158, 315); + this.groupBox3.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(232, 79); - this.groupBox3.TabIndex = 11; + this.groupBox3.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.groupBox3.Size = new System.Drawing.Size(126, 118); + this.groupBox3.TabIndex = 12; this.groupBox3.TabStop = false; this.groupBox3.Text = "MiHoYoBinData"; // - // enableXor + // encrypted // - this.enableXor.AutoSize = true; - this.enableXor.Checked = true; - this.enableXor.CheckState = System.Windows.Forms.CheckState.Checked; - this.enableXor.Location = new System.Drawing.Point(9, 24); - this.enableXor.Name = "enableXor"; - this.enableXor.Size = new System.Drawing.Size(85, 17); - this.enableXor.TabIndex = 12; - this.enableXor.Text = "Enable XOR"; - this.enableXor.UseVisualStyleBackColor = true; + this.encrypted.AutoSize = true; + this.encrypted.Checked = true; + this.encrypted.CheckState = System.Windows.Forms.CheckState.Checked; + this.encrypted.Location = new System.Drawing.Point(20, 35); + this.encrypted.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.encrypted.Name = "encrypted"; + this.encrypted.Size = new System.Drawing.Size(79, 19); + this.encrypted.TabIndex = 12; + this.encrypted.Text = "Encrypted"; + this.encrypted.UseVisualStyleBackColor = true; // // key // this.key.Hexadecimal = true; - this.key.Location = new System.Drawing.Point(124, 21); + this.key.Location = new System.Drawing.Point(54, 72); + this.key.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.key.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.key.Name = "key"; - this.key.Size = new System.Drawing.Size(61, 20); + this.key.Size = new System.Drawing.Size(55, 23); this.key.TabIndex = 8; + this.keyToolTip.SetToolTip(this.key, "Key in hex"); // // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(97, 25); + this.label7.Location = new System.Drawing.Point(20, 74); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(25, 13); + this.label7.Size = new System.Drawing.Size(26, 15); this.label7.TabIndex = 7; this.label7.Text = "Key"; // // ExportOptions // this.AcceptButton = this.OKbutton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.Cancel; - this.ClientSize = new System.Drawing.Size(486, 416); + this.ClientSize = new System.Drawing.Size(567, 480); this.Controls.Add(this.groupBox3); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.Cancel); this.Controls.Add(this.OKbutton); + this.Margin = new System.Windows.Forms.Padding(4); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ExportOptions"; @@ -654,14 +673,13 @@ private System.Windows.Forms.CheckBox openAfterExport; private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps; private System.Windows.Forms.ToolTip exportUvsTooltip; - private System.Windows.Forms.CheckBox exportIndexObject; - private System.Windows.Forms.CheckBox exportAssetBundle; + private System.Windows.Forms.CheckBox collectAnimations; + private System.Windows.Forms.CheckBox skipRenderer; + private System.Windows.Forms.CheckBox exportMiHoYoBinData; private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.CheckBox encrypted; private System.Windows.Forms.NumericUpDown key; private System.Windows.Forms.Label label7; - private System.Windows.Forms.CheckBox enableXor; - private System.Windows.Forms.CheckBox disableRndrr; - private System.Windows.Forms.CheckBox ignoreController; - private System.Windows.Forms.CheckBox disableShader; + private System.Windows.Forms.ToolTip keyToolTip; } } \ No newline at end of file diff --git a/AssetStudioGUI/ExportOptions.cs b/AssetStudioGUI/ExportOptions.cs index 5a21834..b612226 100644 --- a/AssetStudioGUI/ExportOptions.cs +++ b/AssetStudioGUI/ExportOptions.cs @@ -23,13 +23,6 @@ namespace AssetStudioGUI } } openAfterExport.Checked = Properties.Settings.Default.openAfterExport; - exportAssetBundle.Checked = Properties.Settings.Default.exportAssetBundle; - exportIndexObject.Checked = Properties.Settings.Default.exportIndexObject; - disableRndrr.Checked = Properties.Settings.Default.disableRndrr; - disableShader.Checked = Properties.Settings.Default.disableShader; - key.Value = Properties.Settings.Default.key; - enableXor.Checked = Properties.Settings.Default.enableXor; - ignoreController.Checked = Properties.Settings.Default.ignoreController; eulerFilter.Checked = Properties.Settings.Default.eulerFilter; filterPrecision.Value = Properties.Settings.Default.filterPrecision; exportAllNodes.Checked = Properties.Settings.Default.exportAllNodes; @@ -42,6 +35,11 @@ namespace AssetStudioGUI scaleFactor.Value = Properties.Settings.Default.scaleFactor; fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion; fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat; + skipRenderer.Checked = Properties.Settings.Default.skipRenderer; + exportMiHoYoBinData.Checked = Properties.Settings.Default.exportMiHoYoBinData; + collectAnimations.Checked = Properties.Settings.Default.collectAnimations; + encrypted.Checked = Properties.Settings.Default.encrypted; + key.Value = Properties.Settings.Default.key; } private void OKbutton_Click(object sender, EventArgs e) @@ -59,19 +57,6 @@ namespace AssetStudioGUI } } Properties.Settings.Default.openAfterExport = openAfterExport.Checked; - Properties.Settings.Default.exportAssetBundle = exportAssetBundle.Checked; - AssetBundle.Exportable = Properties.Settings.Default.exportAssetBundle; - Properties.Settings.Default.exportIndexObject = exportIndexObject.Checked; - IndexObject.Exportable = Properties.Settings.Default.exportAssetBundle; - Properties.Settings.Default.disableRndrr = disableRndrr.Checked; - Renderer.Parsable = !Properties.Settings.Default.disableRndrr; - Properties.Settings.Default.disableShader = disableShader.Checked; - Shader.Parsable = !Properties.Settings.Default.disableShader; - Properties.Settings.Default.key = (byte)key.Value; - Properties.Settings.Default.enableXor = enableXor.Checked; - MiHoYoBinData.Key = (byte)key.Value; - MiHoYoBinData.doXOR = enableXor.Checked; - Properties.Settings.Default.ignoreController = ignoreController.Checked; Properties.Settings.Default.eulerFilter = eulerFilter.Checked; Properties.Settings.Default.filterPrecision = filterPrecision.Value; Properties.Settings.Default.exportAllNodes = exportAllNodes.Checked; @@ -84,7 +69,15 @@ namespace AssetStudioGUI Properties.Settings.Default.scaleFactor = scaleFactor.Value; Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex; Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex; + Properties.Settings.Default.skipRenderer = skipRenderer.Checked; + Properties.Settings.Default.exportMiHoYoBinData = exportMiHoYoBinData.Checked; + Properties.Settings.Default.collectAnimations = collectAnimations.Checked; + Properties.Settings.Default.encrypted = encrypted.Checked; + Properties.Settings.Default.key = (byte)key.Value; Properties.Settings.Default.Save(); + Renderer.Skipped = !Properties.Settings.Default.skipRenderer; + MiHoYoBinData.Key = (byte)key.Value; + MiHoYoBinData.Encrypted = encrypted.Checked; DialogResult = DialogResult.OK; Close(); } diff --git a/AssetStudioGUI/ExportOptions.resx b/AssetStudioGUI/ExportOptions.resx index 6966b18..2b5ac0b 100644 --- a/AssetStudioGUI/ExportOptions.resx +++ b/AssetStudioGUI/ExportOptions.resx @@ -1,64 +1,4 @@ - - - + @@ -120,4 +60,13 @@ 17, 17 + + 17, 17 + + + 162, 17 + + + 162, 17 + \ No newline at end of file diff --git a/AssetStudioGUI/Exporter.cs b/AssetStudioGUI/Exporter.cs index 18b45c0..b1f27db 100644 --- a/AssetStudioGUI/Exporter.cs +++ b/AssetStudioGUI/Exporter.cs @@ -1,6 +1,6 @@ using AssetStudio; using Newtonsoft.Json; -using System; +using Newtonsoft.Json.Converters; using System.Collections.Generic; using System.IO; using System.Linq; @@ -25,7 +25,7 @@ namespace AssetStudioGUI { using (var file = File.OpenWrite(exportFullPath)) { - image.WriteToStream(file, type); + image.WriteToStream(file, type); } return true; } @@ -115,6 +115,7 @@ namespace AssetStudioGUI switch (m_MiHoYoBinData.Type) { case MiHoYoBinDataType.JSON: + if (!TryExportFile(exportPath, item, ".json", out exportFullPath)) return false; var json = m_MiHoYoBinData.Dump() as string; @@ -125,10 +126,18 @@ namespace AssetStudioGUI } break; case MiHoYoBinDataType.Bytes: - if (!TryExportFile(exportPath, item, ".bin", out exportFullPath)) + var extension = ".bin"; + if (Properties.Settings.Default.restoreExtensionName) + { + if (!string.IsNullOrEmpty(item.Container)) + { + extension = Path.GetExtension(item.Container); + } + } + if (!TryExportFile(exportPath, item, extension, out exportFullPath)) return false; var bytes = m_MiHoYoBinData.Dump() as byte[]; - if (bytes.Length != 0) + if (!bytes.IsNullOrEmpty()) { File.WriteAllBytes(exportFullPath, bytes); return true; @@ -281,22 +290,6 @@ namespace AssetStudioGUI return false; } - public static bool ExportJsonFile(AssetItem item, string exportPath) - { - if (!TryExportFile(exportPath, item, ".json", out var exportFullPath)) - return false; - var str = JsonConvert.SerializeObject(item.Asset, Formatting.Indented); - if (!string.IsNullOrEmpty(str) && str != "{}") - { - File.WriteAllText(exportFullPath, str); - return true; - } - else - { - return ExportRawFile(item, exportPath); - } - } - public static bool ExportRawFile(AssetItem item, string exportPath) { if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath)) @@ -323,16 +316,6 @@ namespace AssetStudioGUI return false; } - public static bool ExportAnimationClip(AssetItem item, string exportPath) - { - if (!TryExportFile(exportPath, item, ".anim", out var exportFullPath)) - return false; - var m_AnimationClip = (AnimationClip)item.Asset; - var str = m_AnimationClip.Convert(Studio.Game); - File.WriteAllText(exportFullPath, str); - return true; - } - public static bool ExportAnimator(AssetItem item, string exportPath, List animationList = null) { var exportFullPath = Path.Combine(exportPath, item.Text, item.Text + ".fbx"); @@ -342,8 +325,8 @@ namespace AssetStudioGUI } var m_Animator = (Animator)item.Asset; var convert = animationList != null - ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, animationList.Select(x => (AnimationClip)x.Asset).ToArray(), Properties.Settings.Default.ignoreController) - : new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, ignoreController: Properties.Settings.Default.ignoreController); + ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); ExportFbx(convert, exportFullPath); return true; } @@ -351,8 +334,8 @@ namespace AssetStudioGUI public static void ExportGameObject(GameObject gameObject, string exportPath, List animationList = null) { var convert = animationList != null - ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, animationList.Select(x => (AnimationClip)x.Asset).ToArray(), Properties.Settings.Default.ignoreController) - : new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, ignoreController: Properties.Settings.Default.ignoreController); + ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx"; ExportFbx(convert, exportPath); } @@ -361,8 +344,8 @@ namespace AssetStudioGUI { var rootName = Path.GetFileNameWithoutExtension(exportPath); var convert = animationList != null - ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, animationList.Select(x => (AnimationClip)x.Asset).ToArray(), Properties.Settings.Default.ignoreController) - : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, ignoreController: Properties.Settings.Default.ignoreController); + ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations); ExportFbx(convert, exportPath); } @@ -429,14 +412,26 @@ namespace AssetStudioGUI case ClassIDType.Animator: return ExportAnimator(item, exportPath); case ClassIDType.AnimationClip: - return ExportAnimationClip(item, exportPath); + return false; case ClassIDType.MiHoYoBinData: return ExportMiHoYoBinData(item, exportPath); default: - return ExportJsonFile(item, exportPath); + return ExportRawFile(item, exportPath); } } + public static bool ExportJSONFile(AssetItem item, string exportPath) + { + if (!TryExportFile(exportPath, item, ".json", out var exportFullPath)) + return false; + + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new StringEnumConverter()); + var str = JsonConvert.SerializeObject(item.Asset, Formatting.Indented, settings); + File.WriteAllText(exportFullPath, str); + return true; + } + public static string FixFileName(string str) { if (str.Length >= 260) return Path.GetRandomFileName(); diff --git a/AssetStudioGUI/GUILogger.cs b/AssetStudioGUI/GUILogger.cs index a2348d3..598044b 100644 --- a/AssetStudioGUI/GUILogger.cs +++ b/AssetStudioGUI/GUILogger.cs @@ -14,8 +14,11 @@ namespace AssetStudioGUI this.action = action; } - public void Log(LoggerEvent loggerEvent, string message) + public void Log(LoggerEvent loggerEvent, string message, bool silent = false) { + if (silent) + return; + switch (loggerEvent) { case LoggerEvent.Error: diff --git a/AssetStudioGUI/Program.cs b/AssetStudioGUI/Program.cs index d156a94..0d085df 100644 --- a/AssetStudioGUI/Program.cs +++ b/AssetStudioGUI/Program.cs @@ -14,9 +14,7 @@ namespace AssetStudioGUI [STAThread] static void Main() { -#if !NETFRAMEWORK Application.SetHighDpiMode(HighDpiMode.SystemAware); -#endif Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new AssetStudioGUIForm()); diff --git a/AssetStudioGUI/Properties/Settings.Designer.cs b/AssetStudioGUI/Properties/Settings.Designer.cs index 43dbd9a..878e29e 100644 --- a/AssetStudioGUI/Properties/Settings.Designer.cs +++ b/AssetStudioGUI/Properties/Settings.Designer.cs @@ -1,73 +1,48 @@ //------------------------------------------------------------------------------ // -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace AssetStudioGUI.Properties -{ - - +namespace AssetStudioGUI.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool console - { - get - { - return ((bool)(this["console"])); - } - set - { - this["console"] = value; - } - } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool displayAll - { - get - { + public bool displayAll { + get { return ((bool)(this["displayAll"])); } - set - { + set { this["displayAll"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool enablePreview - { - get - { + public bool enablePreview { + get { return ((bool)(this["enablePreview"])); } - set - { + set { this["enablePreview"] = value; } } @@ -75,421 +50,349 @@ namespace AssetStudioGUI.Properties [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool enableResolveDependencies - { - get - { - return ((bool)(this["enableResolveDependencies"])); - } - set - { - this["enableResolveDependencies"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool displayInfo - { - get - { + public bool displayInfo { + get { return ((bool)(this["displayInfo"])); } - set - { + set { this["displayInfo"] = value; } } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool openAfterExport - { - get - { - return ((bool)(this["openAfterExport"])); - } - set - { - this["openAfterExport"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public int selectedGame - { - get - { - return ((int)(this["selectedGame"])); - } - set - { - this["selectedGame"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public int assetGroupOption - { - get - { - return ((int)(this["assetGroupOption"])); - } - set - { - this["assetGroupOption"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool convertTexture - { - get - { - return ((bool)(this["convertTexture"])); - } - set - { - this["convertTexture"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool convertAudio - { - get - { - return ((bool)(this["convertAudio"])); - } - set - { - this["convertAudio"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("Png")] - public global::AssetStudio.ImageFormat convertType - { - get - { - return ((global::AssetStudio.ImageFormat)(this["convertType"])); - } - set - { - this["convertType"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportAssetBundle - { - get - { - return ((bool)(this["exportAssetBundle"])); - } - set - { - this["exportAssetBundle"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportIndexObject - { - get - { - return ((bool)(this["exportIndexObject"])); - } - set - { - this["exportIndexObject"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool disableRndrr - { - get - { - return ((bool)(this["disableRndrr"])); - } - set - { - this["disableRndrr"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool disableShader - { - get - { - return ((bool)(this["disableShader"])); - } - set - { - this["disableShader"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("147")] - public byte key - { - get - { - return ((byte)(this["key"])); - } - set - { - this["key"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool enableXor - { - get - { - return ((bool)(this["enableXor"])); - } - set - { - this["enableXor"] = value; - } - } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool ignoreController - { - get - { - return ((bool)(this["ignoreController"])); + public bool openAfterExport { + get { + return ((bool)(this["openAfterExport"])); } - set - { - this["ignoreController"] = value; + set { + this["openAfterExport"] = value; } } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool eulerFilter - { - get - { - return ((bool)(this["eulerFilter"])); - } - set - { - this["eulerFilter"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0.25")] - public decimal filterPrecision - { - get - { - return ((decimal)(this["filterPrecision"])); - } - set - { - this["filterPrecision"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportAllNodes - { - get - { - return ((bool)(this["exportAllNodes"])); - } - set - { - this["exportAllNodes"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportSkins - { - get - { - return ((bool)(this["exportSkins"])); - } - set - { - this["exportSkins"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportAnimations - { - get - { - return ((bool)(this["exportAnimations"])); - } - set - { - this["exportAnimations"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("10")] - public decimal boneSize - { - get - { - return ((decimal)(this["boneSize"])); - } - set - { - this["boneSize"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("3")] - public int fbxVersion - { - get - { - return ((int)(this["fbxVersion"])); - } - set - { - this["fbxVersion"] = value; - } - } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("0")] - public int fbxFormat - { - get - { + public int assetGroupOption { + get { + return ((int)(this["assetGroupOption"])); + } + set { + this["assetGroupOption"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool convertTexture { + get { + return ((bool)(this["convertTexture"])); + } + set { + this["convertTexture"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool convertAudio { + get { + return ((bool)(this["convertAudio"])); + } + set { + this["convertAudio"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Png")] + public global::AssetStudio.ImageFormat convertType { + get { + return ((global::AssetStudio.ImageFormat)(this["convertType"])); + } + set { + this["convertType"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool eulerFilter { + get { + return ((bool)(this["eulerFilter"])); + } + set { + this["eulerFilter"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0.25")] + public decimal filterPrecision { + get { + return ((decimal)(this["filterPrecision"])); + } + set { + this["filterPrecision"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool exportAllNodes { + get { + return ((bool)(this["exportAllNodes"])); + } + set { + this["exportAllNodes"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool exportSkins { + get { + return ((bool)(this["exportSkins"])); + } + set { + this["exportSkins"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool exportAnimations { + get { + return ((bool)(this["exportAnimations"])); + } + set { + this["exportAnimations"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("10")] + public decimal boneSize { + get { + return ((decimal)(this["boneSize"])); + } + set { + this["boneSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("3")] + public int fbxVersion { + get { + return ((int)(this["fbxVersion"])); + } + set { + this["fbxVersion"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int fbxFormat { + get { return ((int)(this["fbxFormat"])); } - set - { + set { this["fbxFormat"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("1")] - public decimal scaleFactor - { - get - { + public decimal scaleFactor { + get { return ((decimal)(this["scaleFactor"])); } - set - { + set { this["scaleFactor"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool exportBlendShape - { - get - { + public bool exportBlendShape { + get { return ((bool)(this["exportBlendShape"])); } - set - { + set { this["exportBlendShape"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool castToBone - { - get - { + public bool castToBone { + get { return ((bool)(this["castToBone"])); } - set - { + set { this["castToBone"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool restoreExtensionName - { - get - { + public bool restoreExtensionName { + get { return ((bool)(this["restoreExtensionName"])); } - set - { + set { this["restoreExtensionName"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool exportAllUvsAsDiffuseMaps - { - get - { + public bool exportAllUvsAsDiffuseMaps { + get { return ((bool)(this["exportAllUvsAsDiffuseMaps"])); } - set - { + set { this["exportAllUvsAsDiffuseMaps"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("147")] + public byte key { + get { + return ((byte)(this["key"])); + } + set { + this["key"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool enableConsole { + get { + return ((bool)(this["enableConsole"])); + } + set { + this["enableConsole"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool encrypted { + get { + return ((bool)(this["encrypted"])); + } + set { + this["encrypted"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool skipRenderer { + get { + return ((bool)(this["skipRenderer"])); + } + set { + this["skipRenderer"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int selectedGame { + get { + return ((int)(this["selectedGame"])); + } + set { + this["selectedGame"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool enableResolveDependencies { + get { + return ((bool)(this["enableResolveDependencies"])); + } + set { + this["enableResolveDependencies"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int selectedCNUnityKey { + get { + return ((int)(this["selectedCNUnityKey"])); + } + set { + this["selectedCNUnityKey"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int selectedAssetMapType { + get { + return ((int)(this["selectedAssetMapType"])); + } + set { + this["selectedAssetMapType"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool exportMiHoYoBinData { + get { + return ((bool)(this["exportMiHoYoBinData"])); + } + set { + this["exportMiHoYoBinData"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool collectAnimations { + get { + return ((bool)(this["collectAnimations"])); + } + set { + this["collectAnimations"] = value; + } + } } } diff --git a/AssetStudioGUI/Properties/Settings.settings b/AssetStudioGUI/Properties/Settings.settings index 4d0ae92..3cbd6aa 100644 --- a/AssetStudioGUI/Properties/Settings.settings +++ b/AssetStudioGUI/Properties/Settings.settings @@ -68,31 +68,31 @@ 147 - + True - + True - + False - - True - - - True - 0 - + True - - False + + 0 - + + 0 + + + True + + True diff --git a/AssetStudioGUI/Studio.cs b/AssetStudioGUI/Studio.cs index 4a8d43b..73f1f41 100644 --- a/AssetStudioGUI/Studio.cs +++ b/AssetStudioGUI/Studio.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Windows.Forms; using System.Xml.Linq; +using static AssetStudio.ImportHelper; using static AssetStudioGUI.Exporter; using Object = AssetStudio.Object; @@ -17,7 +18,8 @@ namespace AssetStudioGUI { Convert, Raw, - Dump + Dump, + JSON } internal enum ExportFilter @@ -27,27 +29,14 @@ namespace AssetStudioGUI Filtered } - internal enum AssetGroupOption - { - ByType, - ByContainer, - BySource, - None - } - - internal enum ExportListType - { - XML - } - internal static class Studio { + public static Game Game; public static AssetsManager assetsManager = new AssetsManager(); public static AssemblyLoader assemblyLoader = new AssemblyLoader(); public static List exportableAssets = new List(); public static List visibleAssets = new List(); internal static Action StatusStripUpdate = x => { }; - public static Game Game; public static int ExtractFolder(string path, string savePath) { @@ -81,13 +70,16 @@ namespace AssetStudioGUI public static int ExtractFile(string fileName, string savePath) { int extractedCount = 0; - var reader = new FileReader(fileName, Game); + var reader = new FileReader(fileName); + reader = reader.PreProcessing(Game); if (reader.FileType == FileType.BundleFile) extractedCount += ExtractBundleFile(reader, savePath); else if (reader.FileType == FileType.WebFile) extractedCount += ExtractWebDataFile(reader, savePath); - else if (reader.FileType == FileType.GameFile) - extractedCount += ExtractGameFile(reader, savePath); + else if (reader.FileType == FileType.BlkFile) + extractedCount += ExtractBlkFile(reader, savePath); + else if (reader.FileType == FileType.BlockFile) + extractedCount += ExtractBlockFile(reader, savePath); else reader.Dispose(); return extractedCount; @@ -96,12 +88,19 @@ namespace AssetStudioGUI private static int ExtractBundleFile(FileReader reader, string savePath) { StatusStripUpdate($"Decompressing {reader.FileName} ..."); - var bundleFile = new BundleFile(reader); - reader.Dispose(); - if (bundleFile.FileList.Length > 0) + try { - var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); - return ExtractStreamFile(extractPath, bundleFile.FileList); + var bundleFile = new BundleFile(reader, Game); + reader.Dispose(); + if (bundleFile.fileList.Length > 0) + { + var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); + return ExtractStreamFile(extractPath, bundleFile.fileList); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mr0k)} but got {Game.Name} ({Game.GetType().Name}) !!"); } return 0; } @@ -119,16 +118,69 @@ namespace AssetStudioGUI return 0; } - private static int ExtractGameFile(FileReader reader, string savePath) + private static int ExtractBlkFile(FileReader reader, string savePath) { - StatusStripUpdate($"Decompressing {reader.FileName}..."); - var gameFile = new GameFile(reader); - reader.Dispose(); - var fileList = gameFile.Bundles.SelectMany(x => x.Value).ToList(); - if (fileList.Count > 0) + int total = 0; + StatusStripUpdate($"Decompressing {reader.FileName} ..."); + try { - var extractPath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(reader.FileName)); - return ExtractStreamFile(extractPath, fileList.ToArray()); + using var stream = BlkUtils.Decrypt(reader, (Blk)Game); + do + { + stream.Offset = stream.RelativePosition; + var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked"); + switch (subReader.FileType) + { + case FileType.BundleFile: + total += ExtractBundleFile(subReader, subSavePath); + break; + case FileType.Mhy0File: + total += ExtractMhy0File(subReader, subSavePath); + break; + } + } while (stream.Remaining > 0); + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Blk)} but got {Game.Name} ({Game.GetType().Name}) !!"); + } + return total; + } + + private static int ExtractBlockFile(FileReader reader, string savePath) + { + int total = 0; + StatusStripUpdate($"Decompressing {reader.FileName} ..."); + using var stream = new BlockStream(reader.BaseStream, 0); + do + { + stream.Offset = stream.RelativePosition; + var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked"); + var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8")); + var subReader = new FileReader(dummyPath, stream, true); + total += ExtractBundleFile(subReader, subSavePath); + } while (stream.Remaining > 0); + return total; + } + + private static int ExtractMhy0File(FileReader reader, string savePath) + { + StatusStripUpdate($"Decompressing {reader.FileName} ..."); + try + { + var mhy0File = new Mhy0File(reader, reader.FullPath, (Mhy0)Game); + reader.Dispose(); + if (mhy0File.fileList.Length > 0) + { + var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); + return ExtractStreamFile(extractPath, mhy0File.fileList); + } + } + catch (InvalidCastException) + { + Logger.Error($"Game type mismatch, Expected {nameof(Mhy0)} but got {Game.Name} ({Game.GetType().Name}) !!"); } return 0; } @@ -157,155 +209,29 @@ namespace AssetStudioGUI return extractedCount; } - public static List BuildAssetMap(List files) + public static void UpdateContainers() { - var assets = new List(); - for (int i = 0; i < files.Count; i++) + if (exportableAssets.Count > 0) { - var file = files[i]; - var reader = new FileReader(file, Game); - var gameFile = new GameFile(reader); - reader.Dispose(); - - foreach (var bundle in gameFile.Bundles) + Logger.Info("Updating Containers..."); + foreach (var asset in exportableAssets) { - foreach (var cab in bundle.Value) + if (int.TryParse(asset.Container, out var value)) { - var dummyPath = Path.Combine(Path.GetDirectoryName(file), cab.fileName); - using (var cabReader = new FileReader(dummyPath, cab.stream, Game)) + var last = unchecked((uint)value); + var path = ResourceIndex.GetAssetPath(last); + if (!string.IsNullOrEmpty(path)) { - if (cabReader.FileType == FileType.AssetsFile) + asset.Container = path; + if (asset.Type == ClassIDType.MiHoYoBinData) { - var assetsFile = new SerializedFile(cabReader, assetsManager, file); - assetsManager.assetsFileList.Add(assetsFile); - - assetsFile.m_Objects = assetsFile.m_Objects.Where(x => x.HasExportableType()).ToList(); - - IndexObject indexObject = null; - var containers = new List<(PPtr, string)>(assetsFile.m_Objects.Count); - var animators = new List<(PPtr, AssetEntry)>(assetsFile.m_Objects.Count); - var objectAssetItemDic = new Dictionary(assetsFile.m_Objects.Count); - foreach (var objInfo in assetsFile.m_Objects) - { - var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo); - var obj = new Object(objectReader); - var asset = new AssetEntry() - { - Source = file, - PathID = objectReader.m_PathID, - Type = objectReader.type, - Container = "" - }; - - var exportable = true; - switch (objectReader.type) - { - case ClassIDType.AssetBundle: - var assetBundle = new AssetBundle(objectReader); - foreach (var m_Container in assetBundle.Container) - { - var preloadIndex = m_Container.Value.preloadIndex; - var preloadSize = m_Container.Value.preloadSize; - var preloadEnd = preloadIndex + preloadSize; - for (int k = preloadIndex; k < preloadEnd; k++) - { - if (Game.Name == "GI" || Game.Name == "GI_CB2" || Game.Name == "GI_CB3") - { - if (long.TryParse(m_Container.Key, out var containerValue)) - { - var last = unchecked((uint)containerValue); - var path = ResourceIndex.GetBundlePath(last); - if (!string.IsNullOrEmpty(path)) - { - containers.Add((assetBundle.PreloadTable[k], path)); - continue; - } - } - } - containers.Add((assetBundle.PreloadTable[k], m_Container.Key)); - } - } - obj = null; - asset.Name = assetBundle.m_Name; - exportable = AssetBundle.Exportable; - break; - case ClassIDType.GameObject: - var gameObject = new GameObject(objectReader); - obj = gameObject; - asset.Name = gameObject.m_Name; - exportable = false; - break; - case ClassIDType.Shader: - asset.Name = objectReader.ReadAlignedString(); - if (string.IsNullOrEmpty(asset.Name)) - { - var m_parsedForm = new SerializedShader(objectReader); - asset.Name = m_parsedForm.m_Name; - } - break; - case ClassIDType.Animator: - var component = new PPtr(objectReader); - animators.Add((component, asset)); - break; - case ClassIDType.MiHoYoBinData: - if (indexObject.Names.TryGetValue(objectReader.m_PathID, out var binName)) - { - var path = ResourceIndex.GetContainerFromBinName(file, binName); - asset.Container = path; - asset.Name = !string.IsNullOrEmpty(path) ? Path.GetFileName(path) : binName; - } - exportable = IndexObject.Exportable; - break; - case ClassIDType.IndexObject: - indexObject = new IndexObject(objectReader); - obj = null; - asset.Name = "IndexObject"; - exportable = IndexObject.Exportable; - break; - default: - asset.Name = objectReader.ReadAlignedString(); - break; - } - if (obj != null) - { - objectAssetItemDic.Add(obj, asset); - assetsFile.AddObject(obj); - } - if (exportable) - { - assets.Add(asset); - } - } - foreach (var pair in animators) - { - if (pair.Item1.TryGet(out var gameObject)) - { - pair.Item2.Name = gameObject.m_Name; - } - else - { - Logger.Warning($"Unable to find GameObject with PathID {pair.Item1.m_PathID}, removing..."); - assets.Remove(pair.Item2); - } - } - foreach ((var pptr, var container) in containers) - { - if (pptr.TryGet(out var obj)) - { - objectAssetItemDic[obj].Container = container; - } - } - assetsManager.assetsFileList.Clear(); + asset.Text = Path.GetFileNameWithoutExtension(path); } } } } - - Logger.Info($"[{i + 1}/{files.Count}] Processed {Path.GetFileName(file)}"); - Progress.Report(i + 1, files.Count); + Logger.Info("Updated !!"); } - - return assets; } public static (string, List) BuildAssetData() @@ -315,6 +241,7 @@ namespace AssetStudioGUI string productName = null; var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count); var objectAssetItemDic = new Dictionary(objectCount); + var mihoyoBinDataNames = new List<(PPtr, string)>(); var containers = new List<(PPtr, string)>(); int i = 0; Progress.Reset(); @@ -322,9 +249,14 @@ namespace AssetStudioGUI { foreach (var asset in assetsFile.Objects) { + if (assetsManager.tokenSource.IsCancellationRequested) + { + Logger.Info("Building asset list has been cancelled !!"); + return (string.Empty, Array.Empty().ToList()); + } var assetItem = new AssetItem(asset); objectAssetItemDic.Add(asset, assetItem); - assetItem.UniqueID = "#" + i; + assetItem.UniqueID = " #" + i; var exportable = false; switch (asset) { @@ -359,7 +291,6 @@ namespace AssetStudioGUI case Font _: case MovieTexture _: case Sprite _: - case Material _: assetItem.Text = ((NamedObject)asset).m_Name; exportable = true; break; @@ -385,35 +316,27 @@ namespace AssetStudioGUI productName = m_PlayerSettings.productName; break; case AssetBundle m_AssetBundle: - foreach (var m_Container in m_AssetBundle.Container) + foreach (var m_Container in m_AssetBundle.m_Container) { var preloadIndex = m_Container.Value.preloadIndex; var preloadSize = m_Container.Value.preloadSize; var preloadEnd = preloadIndex + preloadSize; for (int k = preloadIndex; k < preloadEnd; k++) { - if (Game.Name == "GI" || Game.Name == "GI_CB2" || Game.Name == "GI_CB3") - { - if (long.TryParse(m_Container.Key, out var containerValue)) - { - var last = unchecked((uint)containerValue); - var path = ResourceIndex.GetBundlePath(last); - if (!string.IsNullOrEmpty(path)) - { - containers.Add((m_AssetBundle.PreloadTable[k], path)); - continue; - } - } - } - containers.Add((m_AssetBundle.PreloadTable[k], m_Container.Key)); + containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key)); } } assetItem.Text = m_AssetBundle.m_Name; - exportable = AssetBundle.Exportable; break; case IndexObject m_IndexObject: + foreach(var index in m_IndexObject.AssetMap) + { + mihoyoBinDataNames.Add((index.Value.Object, index.Key)); + } assetItem.Text = "IndexObject"; - exportable = IndexObject.Exportable; + break; + case MiHoYoBinData m_MiHoYoBinData: + exportable = MiHoYoBinData.Exportable; break; case ResourceManager m_ResourceManager: foreach (var m_Container in m_ResourceManager.m_Container) @@ -421,29 +344,6 @@ namespace AssetStudioGUI containers.Add((m_Container.Value, m_Container.Key)); } break; - case MiHoYoBinData m_MiHoYoBinData: - if (m_MiHoYoBinData.assetsFile.ObjectsDic.TryGetValue(2, out var obj) && obj is IndexObject indexObject) - { - if (indexObject.Names.TryGetValue(m_MiHoYoBinData.m_PathID, out var binName)) - { - string path = ""; - var game = GameManager.GetGame("GI"); - if (Path.GetExtension(assetsFile.originalPath) == game.Extension) - { - path = ResourceIndex.GetContainerFromBinName(assetsFile.originalPath, binName); - } - else - { - var last = Convert.ToUInt32(binName, 16); - path = ResourceIndex.GetBundlePath(last) ?? ""; - } - assetItem.Container = path; - assetItem.Text = !string.IsNullOrEmpty(path) ? Path.GetFileName(path) : binName; - } - } - else assetItem.Text = string.Format("BinFile #{0}", assetItem.m_PathID); - exportable = true; - break; case NamedObject m_NamedObject: assetItem.Text = m_NamedObject.m_Name; break; @@ -459,20 +359,32 @@ namespace AssetStudioGUI Progress.Report(++i, objectCount); } } - - StatusStripUpdate("Building container list..."); - - i = 0; - Progress.Reset(); - var containersCount = containers.Count; + foreach((var pptr, var name) in mihoyoBinDataNames) + { + if (pptr.TryGet(out var obj)) + { + var assetItem = objectAssetItemDic[obj]; + if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash)) + { + assetItem.Text = name; + assetItem.Container = hash.ToString(); + } + else assetItem.Text = $"BinFile #{assetItem.m_PathID}"; + } + } foreach ((var pptr, var container) in containers) { if (pptr.TryGet(out var obj)) { objectAssetItemDic[obj].Container = container; } - Progress.Report(++i, containersCount); } + + if (Game.Type.IsGISubGroup()) + { + UpdateContainers(); + } + foreach (var tmp in exportableAssets) { tmp.SetSubItems(); @@ -494,6 +406,12 @@ namespace AssetStudioGUI foreach (var obj in assetsFile.Objects) { + if (assetsManager.tokenSource.IsCancellationRequested) + { + Logger.Info("Building tree structure been cancelled !!"); + return (string.Empty, Array.Empty().ToList()); + } + if (obj is GameObject m_GameObject) { if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode)) @@ -617,11 +535,11 @@ namespace AssetStudioGUI case AssetGroupOption.ByContainer: //container path if (!string.IsNullOrEmpty(asset.Container)) { - exportPath = Path.HasExtension(asset.Container) ? Path.Combine(savePath, Path.GetDirectoryName(asset.Container)) : Path.Combine(savePath, asset.Container); + exportPath = Path.Combine(savePath, Path.GetDirectoryName(asset.Container)); } else { - exportPath = Path.Combine(savePath, asset.TypeString); + exportPath = savePath; } break; case AssetGroupOption.BySource: //source file @@ -662,6 +580,12 @@ namespace AssetStudioGUI exportedCount++; } break; + case ExportType.JSON: + if (ExportJSONFile(asset, exportPath)) + { + exportedCount++; + } + break; } } catch (Exception ex) @@ -688,51 +612,6 @@ namespace AssetStudioGUI }); } - public static void ExportAssetsMap(string savePath, List toExportAssets, ExportListType exportListType) - { - ThreadPool.QueueUserWorkItem(state => - { - Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); - - Progress.Reset(); - - string filename; - switch (exportListType) - { - case ExportListType.XML: - filename = Path.Combine(savePath, $"assets_map_{Game.Name}.xml"); - var doc = new XDocument( - new XElement("Assets", - new XAttribute("filename", filename), - new XAttribute("createdAt", DateTime.UtcNow.ToString("s")), - toExportAssets.Select( - asset => new XElement("Asset", - new XElement("Name", asset.Name), - new XElement("Container", asset.Container), - new XElement("Type", new XAttribute("id", (int)asset.Type), asset.Type.ToString()), - new XElement("PathID", asset.PathID), - new XElement("Source", asset.Source) - ) - ) - ) - ); - doc.Save(filename); - break; - } - - var statusText = $"Finished exporting asset list with {toExportAssets.Count()} items."; - - StatusStripUpdate(statusText); - - Logger.Info($"AssetMap build successfully !!"); - - if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0) - { - OpenFolderInExplorer(savePath); - } - }); - } - public static void ExportAssetsList(string savePath, List toExportAssets, ExportListType exportListType) { ThreadPool.QueueUserWorkItem(state => @@ -756,7 +635,6 @@ namespace AssetStudioGUI new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString), new XElement("PathID", asset.m_PathID), new XElement("Source", asset.SourceFile.fullName), - new XElement("OriginalPath", asset.SourceFile.originalPath), new XElement("Size", asset.FullSize) ) ) diff --git a/AssetStudioUtility/ACL/ACL.cs b/AssetStudioUtility/ACL/ACL.cs index e1c1c40..a93ca1a 100644 --- a/AssetStudioUtility/ACL/ACL.cs +++ b/AssetStudioUtility/ACL/ACL.cs @@ -2,9 +2,9 @@ using System; using System.Runtime.InteropServices; using AssetStudio.PInvoke; -namespace ACL +namespace ACLLibs { - public static class ACL + public static partial class ACL { private const string DLL_NAME = "acl"; static ACL() @@ -27,20 +27,20 @@ namespace ACL #region importfunctions - [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] - private static extern void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); + [LibraryImport(DLL_NAME)] + private static partial void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); #endregion } - public static class SRACL + public static partial class SRACL { private const string DLL_NAME = "sracl"; static SRACL() { DllLoader.PreloadDll(DLL_NAME); } - public static void DecompressAll(uint[] data, out float[] values, out float[] times) + public static void DecompressAll(byte[] data, out float[] values, out float[] times) { var pinned = GCHandle.Alloc(data, GCHandleType.Pinned); var pData = pinned.AddrOfPinnedObject(); @@ -56,8 +56,8 @@ namespace ACL #region importfunctions - [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] - private static extern void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); + [LibraryImport(DLL_NAME)] + private static partial void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); #endregion } diff --git a/AssetStudioUtility/ACL/ACLExtensions.cs b/AssetStudioUtility/ACL/ACLExtensions.cs index 6736625..d64967b 100644 --- a/AssetStudioUtility/ACL/ACLExtensions.cs +++ b/AssetStudioUtility/ACL/ACLExtensions.cs @@ -1,8 +1,10 @@ -namespace AssetStudio +using ACLLibs; + +namespace AssetStudio { public static class ACLExtensions { - public static void Process(this ACLClip m_ACLClip, out float[] values, out float[] times) => ACL.ACL.DecompressAll(m_ACLClip.m_ClipData, out values, out times); - public static void ProcessSR(this ACLClip m_ACLClip, out float[] values, out float[] times) => ACL.SRACL.DecompressAll(m_ACLClip.m_ClipDataUint, out values, out times); + public static void Process(this ACLClip m_ACLClip, out float[] values, out float[] times) => ACL.DecompressAll(m_ACLClip.m_ClipData, out values, out times); + public static void ProcessSR(this ACLClip m_ACLClip, out float[] values, out float[] times) => SRACL.DecompressAll(m_ACLClip.m_ClipData, out values, out times); } } diff --git a/AssetStudioUtility/AnimationClipConverter.cs b/AssetStudioUtility/AnimationClipConverter.cs deleted file mode 100644 index 1b60bc8..0000000 --- a/AssetStudioUtility/AnimationClipConverter.cs +++ /dev/null @@ -1,499 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace AssetStudio -{ - public class AnimationClipConverter - { - private readonly AnimationClip animationClip; - - public static readonly Regex UnknownPathRegex = new Regex($@"^path_[0-9]{{1,10}}$", RegexOptions.Compiled); - - private readonly Dictionary>> m_translations = new Dictionary>>(); - private readonly Dictionary>> m_rotations = new Dictionary>>(); - private readonly Dictionary>> m_scales = new Dictionary>>(); - private readonly Dictionary>> m_eulers = new Dictionary>>(); - private readonly Dictionary>> m_floats = new Dictionary>>(); - private readonly Dictionary> m_pptrs = new Dictionary>(); - - public Vector3Curve[] Translations { get; private set; } - public QuaternionCurve[] Rotations { get; private set; } - public Vector3Curve[] Scales { get; private set; } - public Vector3Curve[] Eulers { get; private set; } - public FloatCurve[] Floats { get; private set; } - public PPtrCurve[] PPtrs { get; private set; } - - public Game Game; - - public AnimationClipConverter(AnimationClip clip, Game game) - { - animationClip = clip; - Game = game; - } - - public static AnimationClipConverter Process(AnimationClip clip, Game game) - { - var converter = new AnimationClipConverter(clip, game); - converter.ProcessInner(); - return converter; - } - private void ProcessInner() - { - var m_Clip = animationClip.m_MuscleClip.m_Clip; - var bindings = animationClip.m_ClipBindingConstant; - var tos = animationClip.FindTOS(); - - var streamedFrames = m_Clip.m_StreamedClip.ReadData(); - var lastDenseFrame = m_Clip.m_DenseClip.m_FrameCount / m_Clip.m_DenseClip.m_SampleRate; - var lastSampleFrame = streamedFrames.Count > 1 ? streamedFrames[streamedFrames.Count - 2].time : 0.0f; - var lastFrame = Math.Max(lastDenseFrame, lastSampleFrame); - - if (m_Clip.m_ACLClip.IsSet && Game.Name != "SR_CB2" && Game.Name != "SR_CB3") - { - var lastACLFrame = ProcessACLClip(m_Clip, bindings, tos); - lastFrame = Math.Max(lastFrame, lastACLFrame); - } - ProcessStreams(streamedFrames, bindings, tos, m_Clip.m_DenseClip.m_SampleRate); - ProcessDenses(m_Clip, bindings, tos); - if (m_Clip.m_ACLClip.IsSet && (Game.Name == "SR_CB2" || Game.Name == "SR_CB3")) - { - var lastACLFrame = ProcessACLClip(m_Clip, bindings, tos); - lastFrame = Math.Max(lastFrame, lastACLFrame); - } - if (m_Clip.m_ConstantClip != null) - { - ProcessConstant(m_Clip, bindings, tos, lastFrame); - } - CreateCurves(); - } - - private void CreateCurves() - { - Translations = m_translations.Select(t => new Vector3Curve(t.Key, t.Value)).ToArray(); - Rotations = m_rotations.Select(t => new QuaternionCurve(t.Key, t.Value)).ToArray(); - Scales = m_scales.Select(t => new Vector3Curve(t.Key, t.Value)).ToArray(); - Eulers = m_eulers.Select(t => new Vector3Curve(t.Key, t.Value)).ToArray(); - Floats = m_floats.Select(t => new FloatCurve(t.Key, t.Value)).ToArray(); - PPtrs = m_pptrs.Select(t => new PPtrCurve(t.Key, t.Value)).ToArray(); - } - - private void ProcessStreams(List streamFrames, AnimationClipBindingConstant bindings, Dictionary tos, float sampleRate) - { - var curveValues = new float[4]; - var inSlopeValues = new float[4]; - var outSlopeValues = new float[4]; - var interval = 1.0f / sampleRate; - - // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) - // last one (index [count - 1]) is +Infinity - // it is made for slope processing, but we don't need them - for (var frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) - { - var frame = streamFrames[frameIndex]; - for (var curveIndex = 0; curveIndex < frame.keyList.Length;) - { - var curve = frame.keyList[curveIndex]; - var index = curve.index; - if (animationClip.m_MuscleClip.m_Clip.m_ACLClip.IsSet && Game.Name != "SR_CB2" && Game.Name != "SR_CB3") - index += (int)animationClip.m_MuscleClip.m_Clip.m_ACLClip.m_CurveCount; - var binding = bindings.FindBinding(index); - - var path = GetCurvePath(tos, binding.path); - if (binding.typeID == ClassIDType.Transform) - { - GetPreviousFrame(streamFrames, curve.index, frameIndex, out var prevFrameIndex, out var prevCurveIndex); - var dimension = binding.GetDimension(); - for (int key = 0; key < dimension; key++) - { - var keyCurve = frame.keyList[curveIndex]; - var prevFrame = streamFrames[prevFrameIndex]; - var prevKeyCurve = prevFrame.keyList[prevCurveIndex + key]; - var deltaTime = frame.time - prevFrame.time; - curveValues[key] = keyCurve.value; - inSlopeValues[key] = prevKeyCurve.CalculateNextInSlope(deltaTime, keyCurve); - outSlopeValues[key] = keyCurve.outSlope; - curveIndex = GetNextCurve(frame, curveIndex); - } - - AddTransformCurve(frame.time, binding.attribute, curveValues, inSlopeValues, outSlopeValues, 0, path); - } - else - { - if (binding.customType == 8) - { - AddAnimatorMuscleCurve(binding, frame.time, frame.keyList[curveIndex].value); - } - else if (binding.customType == 20) - { - AddBlendShapeCurve(binding, path, frame.time, frame.keyList[curveIndex].value); - } - curveIndex = GetNextCurve(frame, curveIndex); - } - } - } - } - - private void ProcessDenses(Clip clip, AnimationClipBindingConstant bindings, Dictionary tos) - { - var dense = clip.m_DenseClip; - var streamCount = clip.m_StreamedClip.curveCount; - var slopeValues = new float[4]; // no slopes - 0 values - for (var frameIndex = 0; frameIndex < dense.m_FrameCount; frameIndex++) - { - var time = frameIndex / dense.m_SampleRate; - var frameOffset = frameIndex * (int)dense.m_CurveCount; - for (var curveIndex = 0; curveIndex < dense.m_CurveCount;) - { - var index = (int)streamCount + curveIndex; - if (clip.m_ACLClip.IsSet && Game.Name != "SR_CB2" && Game.Name != "SR_CB3") - index += (int)clip.m_ACLClip.m_CurveCount; - var binding = bindings.FindBinding(index); - var path = GetCurvePath(tos, binding.path); - var framePosition = frameOffset + curveIndex; - if (binding.typeID == ClassIDType.Transform) - { - AddTransformCurve(time, binding.attribute, dense.m_SampleArray, slopeValues, slopeValues, framePosition, path); - curveIndex += binding.GetDimension(); - } - else - { - if (binding.customType == 8) - { - AddAnimatorMuscleCurve(binding, time, dense.m_SampleArray[framePosition]); - } - else if (binding.customType == 20) - { - AddBlendShapeCurve(binding, path, time, dense.m_SampleArray[framePosition]); - } - curveIndex++; - } - } - } - } - private float ProcessACLClip(Clip clip, AnimationClipBindingConstant bindings, Dictionary tos) - { - float[] values; - float[] times; - var acl = clip.m_ACLClip; - if (Game.Name != "SR_CB2" && Game.Name != "SR_CB3") - { - acl.Process(out values, out times); - } - else - { - acl.ProcessSR(out values, out times); - } - float[] slopeValues = new float[4]; // no slopes - 0 values - - int frameCount = times.Length; - for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) - { - float time = times[frameIndex]; - int frameOffset = frameIndex * (int)acl.m_CurveCount; - for (int curveIndex = 0; curveIndex < acl.m_CurveCount;) - { - var index = curveIndex; - if (Game.Name == "SR_CB2" || Game.Name == "SR_CB3") - index += (int)(clip.m_StreamedClip.curveCount + clip.m_DenseClip.m_CurveCount); - GenericBinding binding = bindings.FindBinding(index); - string path = GetCurvePath(tos, binding.path); - int framePosition = frameOffset + curveIndex; - if (binding.typeID == ClassIDType.Transform) - { - AddTransformCurve(time, binding.attribute, values, slopeValues, slopeValues, framePosition, path); - curveIndex += binding.GetDimension(); - } - else - { - if (binding.customType == 8) - { - AddAnimatorMuscleCurve(binding, time, values[framePosition]); - } - else if (binding.customType == 20) - { - AddBlendShapeCurve(binding, path, time, values[framePosition]); - } - curveIndex++; - } - } - } - - return times[frameCount - 1]; - } - private void ProcessConstant(Clip clip, AnimationClipBindingConstant bindings, Dictionary tos, float lastFrame) - { - var constant = clip.m_ConstantClip; - var streamCount = clip.m_StreamedClip.curveCount; - var denseCount = clip.m_DenseClip.m_CurveCount; - var slopeValues = new float[4]; // no slopes - 0 values - - // only first and last frames - var time = 0.0f; - for (var i = 0; i < 2; i++, time += lastFrame) - { - for (var curveIndex = 0; curveIndex < constant.data.Length;) - { - var index = (int)(streamCount + denseCount + curveIndex); - if (clip.m_ACLClip.IsSet) - index += (int)clip.m_ACLClip.m_CurveCount; - GenericBinding binding = bindings.FindBinding(index); - string path = GetCurvePath(tos, binding.path); - if (binding.typeID == ClassIDType.Transform) - { - AddTransformCurve(time, binding.attribute, constant.data, slopeValues, slopeValues, curveIndex, path); - curveIndex += binding.GetDimension(); - } - else - { - if (binding.customType == 8) - { - AddAnimatorMuscleCurve(binding, time, constant.data[curveIndex]); - } - else if (binding.customType == 20) - { - AddBlendShapeCurve(binding, path, time, constant.data[curveIndex]); - } - curveIndex++; - } - } - } - } - - private void AddTransformCurve(float time, uint transType, float[] curveValues, - float[] inSlopeValues, float[] outSlopeValues, int offset, string path) - { - switch (transType) - { - case 1: - { - Vector3Curve curve = new Vector3Curve(path); - if (!m_translations.TryGetValue(curve, out List> transCurve)) - { - transCurve = new List>(); - m_translations.Add(curve, transCurve); - } - - float x = curveValues[offset + 0]; - float y = curveValues[offset + 1]; - float z = curveValues[offset + 2]; - - float inX = inSlopeValues[0]; - float inY = inSlopeValues[1]; - float inZ = inSlopeValues[2]; - - float outX = outSlopeValues[0]; - float outY = outSlopeValues[1]; - float outZ = outSlopeValues[2]; - - Vector3 value = new Vector3(x, y, z); - Vector3 inSlope = new Vector3(inX, inY, inZ); - Vector3 outSlope = new Vector3(outX, outY, outZ); - Keyframe transKey = new Keyframe(time, value, inSlope, outSlope, Keyframe.DefaultVector3Weight); - transCurve.Add(transKey); - } - break; - - case 2: - { - QuaternionCurve curve = new QuaternionCurve(path); - if (!m_rotations.TryGetValue(curve, out List> rotCurve)) - { - rotCurve = new List>(); - m_rotations.Add(curve, rotCurve); - } - - float x = curveValues[offset + 0]; - float y = curveValues[offset + 1]; - float z = curveValues[offset + 2]; - float w = curveValues[offset + 3]; - - float inX = inSlopeValues[0]; - float inY = inSlopeValues[1]; - float inZ = inSlopeValues[2]; - float inW = inSlopeValues[3]; - - float outX = outSlopeValues[0]; - float outY = outSlopeValues[1]; - float outZ = outSlopeValues[2]; - float outW = outSlopeValues[3]; - - Quaternion value = new Quaternion(x, y, z, w); - Quaternion inSlope = new Quaternion(inX, inY, inZ, inW); - Quaternion outSlope = new Quaternion(outX, outY, outZ, outW); - Keyframe rotKey = new Keyframe(time, value, inSlope, outSlope, Keyframe.DefaultQuaternionWeight); - rotCurve.Add(rotKey); - } - break; - - case 3: - { - Vector3Curve curve = new Vector3Curve(path); - if (!m_scales.TryGetValue(curve, out List> scaleCurve)) - { - scaleCurve = new List>(); - m_scales.Add(curve, scaleCurve); - } - - float x = curveValues[offset + 0]; - float y = curveValues[offset + 1]; - float z = curveValues[offset + 2]; - - float inX = inSlopeValues[0]; - float inY = inSlopeValues[1]; - float inZ = inSlopeValues[2]; - - float outX = outSlopeValues[0]; - float outY = outSlopeValues[1]; - float outZ = outSlopeValues[2]; - - Vector3 value = new Vector3(x, y, z); - Vector3 inSlope = new Vector3(inX, inY, inZ); - Vector3 outSlope = new Vector3(outX, outY, outZ); - Keyframe scaleKey = new Keyframe(time, value, inSlope, outSlope, Keyframe.DefaultVector3Weight); - scaleCurve.Add(scaleKey); - } - break; - - case 4: - { - Vector3Curve curve = new Vector3Curve(path); - if (!m_eulers.TryGetValue(curve, out List> eulerCurve)) - { - eulerCurve = new List>(); - m_eulers.Add(curve, eulerCurve); - } - - float x = curveValues[offset + 0]; - float y = curveValues[offset + 1]; - float z = curveValues[offset + 2]; - - float inX = inSlopeValues[0]; - float inY = inSlopeValues[1]; - float inZ = inSlopeValues[2]; - - float outX = outSlopeValues[0]; - float outY = outSlopeValues[1]; - float outZ = outSlopeValues[2]; - - Vector3 value = new Vector3(x, y, z); - Vector3 inSlope = new Vector3(inX, inY, inZ); - Vector3 outSlope = new Vector3(outX, outY, outZ); - Keyframe eulerKey = new Keyframe(time, value, inSlope, outSlope, Keyframe.DefaultVector3Weight); - eulerCurve.Add(eulerKey); - } - break; - - default: - throw new NotImplementedException(transType.ToString()); - } - } - - private void AddAnimatorMuscleCurve(GenericBinding binding, float time, float value) - { - FloatCurve curve = new FloatCurve(string.Empty, binding.GetClipMuscle(), ClassIDType.Animator, new PPtr(0, 0, null)); - AddFloatKeyframe(curve, time, value); - } - - private void AddBlendShapeCurve(GenericBinding binding, string path, float time, float value) - { - var attribute = ""; - const string Prefix = "blendShape."; - if (UnknownPathRegex.IsMatch(path)) - { - attribute = Prefix + binding.attribute; - } - - foreach (GameObject root in animationClip.FindRoots().ToArray()) - { - Transform rootTransform = root.GetTransform(); - Transform child = rootTransform.FindChild(path); - if (child == null) - { - continue; - } - SkinnedMeshRenderer skin = null; - if (child.m_GameObject.TryGet(out var gameObject)) - { - skin = gameObject.FindComponent(); - } - if (skin == null) - { - continue; - } - if (!skin.m_Mesh.TryGet(out var mesh)) - { - continue; - } - string shapeName = mesh.FindBlendShapeNameByCRC(binding.attribute); - if (shapeName == null) - { - continue; - } - - attribute = Prefix + shapeName; - } - attribute = Prefix + attribute; - - FloatCurve curve = new FloatCurve(path, attribute, binding.typeID, binding.script.CastTo()); - AddFloatKeyframe(curve, time, value); - } - - private void AddFloatKeyframe(FloatCurve curve, float time, float value) - { - if (!m_floats.TryGetValue(curve, out List> floatCurve)) - { - floatCurve = new List>(); - m_floats.Add(curve, floatCurve); - } - - Keyframe floatKey = new Keyframe(time, value, Keyframe.DefaultFloatWeight); - floatCurve.Add(floatKey); - } - - private void GetPreviousFrame(List streamFrames, int curveID, int currentFrame, out int frameIndex, out int curveIndex) - { - for (frameIndex = currentFrame - 1; frameIndex >= 0; frameIndex--) - { - var frame = streamFrames[frameIndex]; - for (curveIndex = 0; curveIndex < frame.keyList.Length; curveIndex++) - { - var curve = frame.keyList[curveIndex]; - if (curve.index == curveID) - { - return; - } - } - } - throw new Exception($"There is no curve with index {curveID} in any of previous frames"); - } - - private int GetNextCurve(StreamedClip.StreamedFrame frame, int currentCurve) - { - var curve = frame.keyList[currentCurve]; - int i = currentCurve + 1; - for (; i < frame.keyList.Length; i++) - { - if (frame.keyList[i].index != curve.index) - { - return i; - } - } - return i; - } - - private static string GetCurvePath(Dictionary tos, uint hash) - { - if (tos.TryGetValue(hash, out string path)) - { - return path; - } - else - { - return $"path_{hash}"; - } - } - - } -} \ No newline at end of file diff --git a/AssetStudioUtility/AnimationClipExtensions.cs b/AssetStudioUtility/AnimationClipExtensions.cs deleted file mode 100644 index 9bce0ab..0000000 --- a/AssetStudioUtility/AnimationClipExtensions.cs +++ /dev/null @@ -1,250 +0,0 @@ -using System.IO; -using System.Linq; -using System.Text; - -namespace AssetStudio -{ - public static class AnimationClipExtensions - { - public static string Convert(this AnimationClip animationClip, Game game) - { - var converter = AnimationClipConverter.Process(animationClip, game); - animationClip.m_RotationCurves = converter.Rotations.Union(animationClip.m_RotationCurves).ToArray(); - animationClip.m_EulerCurves = converter.Eulers.Union(animationClip.m_EulerCurves).ToArray(); - animationClip.m_PositionCurves = converter.Translations.Union(animationClip.m_PositionCurves).ToArray(); - animationClip.m_ScaleCurves = converter.Scales.Union(animationClip.m_ScaleCurves).ToArray(); - animationClip.m_FloatCurves = converter.Floats.Union(animationClip.m_FloatCurves).ToArray(); - animationClip.m_PPtrCurves = converter.PPtrs.Union(animationClip.m_PPtrCurves).ToArray(); - return ConvertSerializedAnimationClip(animationClip); - } - - public static string ConvertSerializedAnimationClip(AnimationClip animationClip) - { - var sb = new StringBuilder(); - using (var stringWriter = new StringWriter(sb)) - { - YAMLWriter writer = new YAMLWriter(); - YAMLDocument doc = ExportYAMLDocument(animationClip); - writer.AddDocument(doc); - writer.Write(stringWriter); - return sb.ToString(); - } - } - - public static YAMLDocument ExportYAMLDocument(AnimationClip animationClip) - { - YAMLDocument document = new YAMLDocument(); - YAMLMappingNode root = document.CreateMappingRoot(); - root.Tag = ((int)ClassIDType.AnimationClip).ToString(); - root.Anchor = ((int)ClassIDType.AnimationClip * 100000).ToString(); - YAMLMappingNode node = (YAMLMappingNode)animationClip.ExportYAML(); - root.Add(ClassIDType.AnimationClip.ToString(), node); - return document; - } - public static string GetClipMuscle(this GenericBinding genericBinding) => ClipMuscles[genericBinding.attribute] ?? $"unknown_{genericBinding.attribute}"; - - public static string[] ClipMuscles = - { - "MotionT.x", - "MotionT.y", - "MotionT.z", - "MotionQ.x", - "MotionQ.y", - "MotionQ.z", - "MotionQ.w", - "RootT.x", - "RootT.y", - "RootT.z", - "RootQ.x", - "RootQ.y", - "RootQ.z", - "RootQ.w", - "LeftFootT.x", - "LeftFootT.y", - "LeftFootT.z", - "LeftFootQ.x", - "LeftFootQ.y", - "LeftFootQ.z", - "LeftFootQ.w", - "RightFootT.x", - "RightFootT.y", - "RightFootT.z", - "RightFootQ.x", - "RightFootQ.y", - "RightFootQ.z", - "RightFootQ.w", - "LeftHandT.x", - "LeftHandT.y", - "LeftHandT.z", - "LeftHandQ.x", - "LeftHandQ.y", - "LeftHandQ.z", - "LeftHandQ.w", - "RightHandT.x", - "RightHandT.y", - "RightHandT.z", - "RightHandQ.x", - "RightHandQ.y", - "RightHandQ.z", - "RightHandQ.w", - "Spine Front-Back", - "Spine Left-Right", - "Spine Twist Left-Right", - "Chest Front-Back", - "Chest Left-Right", - "Chest Twist Left-Right", - "UpperChest Front-Back", - "UpperChest Left-Right", - "UpperChest Twist Left-Right", - "Neck Nod Down-Up", - "Neck Tilt Left-Right", - "Neck Turn Left-Right", - "Head Nod Down-Up", - "Head Tilt Left-Right", - "Head Turn Left-Right", - "Left Eye Down-Up", - "Left Eye In-Out", - "Right Eye Down-Up", - "Right Eye In-Out", - "Jaw Close", - "Jaw Left-Right", - "Left Upper Leg Front-Back", - "Left Upper Leg In-Out", - "Left Upper Leg Twist In-Out", - "Left Lower Leg Stretch", - "Left Lower Leg Twist In-Out", - "Left Foot Up-Down", - "Left Foot Twist In-Out", - "Left Toes Up-Down", - "Right Upper Leg Front-Back", - "Right Upper Leg In-Out", - "Right Upper Leg Twist In-Out", - "Right Lower Leg Stretch", - "Right Lower Leg Twist In-Out", - "Right Foot Up-Down", - "Right Foot Twist In-Out", - "Right Toes Up-Down", - "Left Shoulder Down-Up", - "Left Shoulder Front-Back", - "Left Arm Down-Up", - "Left Arm Front-Back", - "Left Arm Twist In-Out", - "Left Forearm Stretch", - "Left Forearm Twist In-Out", - "Left Hand Down-Up", - "Left Hand In-Out", - "Right Shoulder Down-Up", - "Right Shoulder Front-Back", - "Right Arm Down-Up", - "Right Arm Front-Back", - "Right Arm Twist In-Out", - "Right Forearm Stretch", - "Right Forearm Twist In-Out", - "Right Hand Down-Up", - "Right Hand In-Out", - "LeftHand.Thumb.1 Stretched", - "LeftHand.Thumb.Spread", - "LeftHand.Thumb.2 Stretched", - "LeftHand.Thumb.3 Stretched", - "LeftHand.Index.1 Stretched", - "LeftHand.Index.Spread", - "LeftHand.Index.2 Stretched", - "LeftHand.Index.3 Stretched", - "LeftHand.Middle.1 Stretched", - "LeftHand.Middle.Spread", - "LeftHand.Middle.2 Stretched", - "LeftHand.Middle.3 Stretched", - "LeftHand.Ring.1 Stretched", - "LeftHand.Ring.Spread", - "LeftHand.Ring.2 Stretched", - "LeftHand.Ring.3 Stretched", - "LeftHand.Little.1 Stretched", - "LeftHand.Little.Spread", - "LeftHand.Little.2 Stretched", - "LeftHand.Little.3 Stretched", - "RightHand.Thumb.1 Stretched", - "RightHand.Thumb.Spread", - "RightHand.Thumb.2 Stretched", - "RightHand.Thumb.3 Stretched", - "RightHand.Index.1 Stretched", - "RightHand.Index.Spread", - "RightHand.Index.2 Stretched", - "RightHand.Index.3 Stretched", - "RightHand.Middle.1 Stretched", - "RightHand.Middle.Spread", - "RightHand.Middle.2 Stretched", - "RightHand.Middle.3 Stretched", - "RightHand.Ring.1 Stretched", - "RightHand.Ring.Spread", - "RightHand.Ring.2 Stretched", - "RightHand.Ring.3 Stretched", - "RightHand.Little.1 Stretched", - "RightHand.Little.Spread", - "RightHand.Little.2 Stretched", - "RightHand.Little.3 Stretched", - "SpineTDOF.x", - "SpineTDOF.y", - "SpineTDOF.z", - "ChestTDOF.x", - "ChestTDOF.y", - "ChestTDOF.z", - "UpperChestTDOF.x", - "UpperChestTDOF.y", - "UpperChestTDOF.z", - "NeckTDOF.x", - "NeckTDOF.y", - "NeckTDOF.z", - "HeadTDOF.x", - "HeadTDOF.y", - "HeadTDOF.z", - "LeftUpperLegTDOF.x", - "LeftUpperLegTDOF.y", - "LeftUpperLegTDOF.z", - "LeftLowerLegTDOF.x", - "LeftLowerLegTDOF.y", - "LeftLowerLegTDOF.z", - "LeftFootTDOF.x", - "LeftFootTDOF.y", - "LeftFootTDOF.z", - "LeftToesTDOF.x", - "LeftToesTDOF.y", - "LeftToesTDOF.z", - "RightUpperLegTDOF.x", - "RightUpperLegTDOF.y", - "RightUpperLegTDOF.z", - "RightLowerLegTDOF.x", - "RightLowerLegTDOF.y", - "RightLowerLegTDOF.z", - "RightFootTDOF.x", - "RightFootTDOF.y", - "RightFootTDOF.z", - "RightToesTDOF.x", - "RightToesTDOF.y", - "RightToesTDOF.z", - "LeftShoulderTDOF.x", - "LeftShoulderTDOF.y", - "LeftShoulderTDOF.z", - "LeftUpperArmTDOF.x", - "LeftUpperArmTDOF.y", - "LeftUpperArmTDOF.z", - "LeftLowerArmTDOF.x", - "LeftLowerArmTDOF.y", - "LeftLowerArmTDOF.z", - "LeftHandTDOF.x", - "LeftHandTDOF.y", - "LeftHandTDOF.z", - "RightShoulderTDOF.x", - "RightShoulderTDOF.y", - "RightShoulderTDOF.z", - "RightUpperArmTDOF.x", - "RightUpperArmTDOF.y", - "RightUpperArmTDOF.z", - "RightLowerArmTDOF.x", - "RightLowerArmTDOF.y", - "RightLowerArmTDOF.z", - "RightHandTDOF.x", - "RightHandTDOF.y", - "RightHandTDOF.z", - }; - } -} diff --git a/AssetStudioUtility/AssetStudioUtility.csproj b/AssetStudioUtility/AssetStudioUtility.csproj index ae5b4d5..26f650d 100644 --- a/AssetStudioUtility/AssetStudioUtility.csproj +++ b/AssetStudioUtility/AssetStudioUtility.csproj @@ -1,16 +1,19 @@ - net6.0 - 0.18.60 - 0.18.60 - 0.18.60 - Copyright © Razmoth 2022; Copyright © Perfare 2018-2022 - embedded + net7.0 + 0.80.30 + 0.80.30 + 0.80.30 + Copyright © Perfare 2018-2022 + embedded + true - + + + @@ -18,7 +21,6 @@ - diff --git a/AssetStudioUtility/AudioClipConverter.cs b/AssetStudioUtility/AudioClipConverter.cs index 458334e..5499f5c 100644 --- a/AssetStudioUtility/AudioClipConverter.cs +++ b/AssetStudioUtility/AudioClipConverter.cs @@ -23,7 +23,7 @@ namespace AssetStudio var result = Factory.System_Create(out var system); if (result != RESULT.OK) return null; - result = system.init(1, INITFLAGS.NORMAL, IntPtr.Zero); + result = system.init(1, INITFLAGS.NORMAL, nint.Zero); if (result != RESULT.OK) return null; exinfo.cbsize = Marshal.SizeOf(exinfo); diff --git a/AssetStudioUtility/ConsoleHelper.cs b/AssetStudioUtility/ConsoleHelper.cs index a4363a1..22c348c 100644 --- a/AssetStudioUtility/ConsoleHelper.cs +++ b/AssetStudioUtility/ConsoleHelper.cs @@ -1,24 +1,23 @@ -using System; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; namespace AssetStudio { - public static class ConsoleHelper + public static partial class ConsoleHelper { - [DllImport("kernel32.dll", SetLastError = true)] + [LibraryImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AllocConsole(); + public static partial bool AllocConsole(); - [DllImport("kernel32.dll", SetLastError = true)] + [LibraryImport("kernel32.dll", EntryPoint = "SetConsoleTitleA", SetLastError = true, StringMarshalling = StringMarshalling.Utf8)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetConsoleTitle(string lpConsoleTitle); + public static partial bool SetConsoleTitle(string lpConsoleTitle); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetConsoleWindow(); + [LibraryImport("kernel32.dll", SetLastError = true)] + public static partial nint GetConsoleWindow(); - [DllImport("user32.dll", SetLastError = true)] + [LibraryImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + public static partial bool ShowWindow(nint hWnd, int nCmdShow); public const int SW_HIDE = 0; public const int SW_SHOW = 5; diff --git a/AssetStudioUtility/FontHelper.cs b/AssetStudioUtility/FontHelper.cs new file mode 100644 index 0000000..c94fa68 --- /dev/null +++ b/AssetStudioUtility/FontHelper.cs @@ -0,0 +1,10 @@ +using System.Runtime.InteropServices; + +namespace AssetStudio +{ + public static partial class FontHelper + { + [LibraryImport("gdi32.dll")] + public static partial nint AddFontMemResourceEx(nint pbFont, uint cbFont, nint pdv, ref uint pcFonts); + } +} diff --git a/AssetStudioUtility/ModelConverter.cs b/AssetStudioUtility/ModelConverter.cs index b9a4320..5b7b2d2 100644 --- a/AssetStudioUtility/ModelConverter.cs +++ b/AssetStudioUtility/ModelConverter.cs @@ -1,5 +1,4 @@ -using SevenZip; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,6 +14,7 @@ namespace AssetStudio public List AnimationList { get; protected set; } = new List(); public List MorphList { get; protected set; } = new List(); + private Game Game; private ImageFormat imageFormat; private Avatar avatar; private HashSet animationClipHashSet = new HashSet(); @@ -23,18 +23,17 @@ namespace AssetStudio private Dictionary textureNameDictionary = new Dictionary(); private Dictionary transformDictionary = new Dictionary(); Dictionary morphChannelNames = new Dictionary(); - private Game Game; - public ModelConverter(GameObject m_GameObject, ImageFormat imageFormat, Game game, AnimationClip[] animationList = null, bool ignoreController = true) + public ModelConverter(GameObject m_GameObject, ImageFormat imageFormat, Game game, bool collectAnimations, AnimationClip[] animationList = null) { Game = game; this.imageFormat = imageFormat; if (m_GameObject.m_Animator != null) { InitWithAnimator(m_GameObject.m_Animator); - if (animationList == null) + if (animationList == null && collectAnimations) { - CollectAnimationClip(m_GameObject.m_Animator, ignoreController); + CollectAnimationClip(m_GameObject.m_Animator); } } else @@ -51,16 +50,16 @@ namespace AssetStudio ConvertAnimations(); } - public ModelConverter(string rootName, List m_GameObjects, ImageFormat imageFormat, Game game, AnimationClip[] animationList = null, bool ignoreController = true) + public ModelConverter(string rootName, List m_GameObjects, ImageFormat imageFormat, Game game, bool collectAnimations, AnimationClip[] animationList = null) { Game = game; this.imageFormat = imageFormat; RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One); foreach (var m_GameObject in m_GameObjects) { - if (m_GameObject.m_Animator != null && animationList == null) + if (m_GameObject.m_Animator != null && animationList == null && collectAnimations) { - CollectAnimationClip(m_GameObject.m_Animator, ignoreController); + CollectAnimationClip(m_GameObject.m_Animator); } var m_Transform = m_GameObject.m_Transform; @@ -82,14 +81,14 @@ namespace AssetStudio ConvertAnimations(); } - public ModelConverter(Animator m_Animator, ImageFormat imageFormat, Game game, AnimationClip[] animationList = null, bool ignoreController = true) + public ModelConverter(Animator m_Animator, ImageFormat imageFormat, Game game, bool collectAnimations, AnimationClip[] animationList = null) { Game = game; this.imageFormat = imageFormat; InitWithAnimator(m_Animator); - if (animationList == null) + if (animationList == null && collectAnimations) { - CollectAnimationClip(m_Animator, ignoreController); + CollectAnimationClip(m_Animator); } else { @@ -185,9 +184,9 @@ namespace AssetStudio } } - private void CollectAnimationClip(Animator m_Animator, bool ignoreController) + private void CollectAnimationClip(Animator m_Animator) { - if (m_Animator.m_Controller.TryGet(out var m_Controller) && !ignoreController) + if (m_Animator.m_Controller.TryGet(out var m_Controller)) { switch (m_Controller) { @@ -512,7 +511,10 @@ namespace AssetStudio var shapeChannel = mesh.m_Shapes.channels[i]; var blendShapeName = "blendShape." + shapeChannel.name; - morphChannelNames[CRC.CalculateDigestUTF8(blendShapeName)] = blendShapeName; + var crc = new SevenZip.CRC(); + var bytes = Encoding.UTF8.GetBytes(blendShapeName); + crc.Update(bytes, 0, (uint)bytes.Length); + morphChannelNames[crc.GetDigest()] = blendShapeName; channel.Name = shapeChannel.name.Split('.').Last(); channel.KeyframeList = new List(shapeChannel.frameCount); @@ -796,7 +798,7 @@ namespace AssetStudio foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves) { var track = iAnim.FindTrack(FixBonePath(animationClip, m_CompressedRotationCurve.m_Path)); - + var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems; var data = m_CompressedRotationCurve.m_Times.UnpackInts(); var times = new float[numKeys]; @@ -807,7 +809,7 @@ namespace AssetStudio times[i] = t * 0.01f; } var quats = m_CompressedRotationCurve.m_Values.UnpackQuats(); - + for (int i = 0; i < numKeys; i++) { var quat = quats[i]; @@ -861,7 +863,7 @@ namespace AssetStudio { channelName = channelName.Substring(dotPos + 1); } - + var path = FixBonePath(animationClip, m_FloatCurve.path); if (string.IsNullOrEmpty(path)) { @@ -884,7 +886,7 @@ namespace AssetStudio var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding(); var m_ACLClip = m_Clip.m_ACLClip; var aclCount = m_ACLClip.m_CurveCount; - if (m_ACLClip.m_CurveCount != 0 && Game.Name != "SR_CB2" && Game.Name != "SR_CB3") + if (!m_ACLClip.m_ClipData.IsNullOrEmpty() && !Game.Type.IsSRGroup()) { m_ACLClip.Process(out var values, out var times); for (int frameIndex = 0; frameIndex < times.Length; frameIndex++) @@ -896,7 +898,7 @@ namespace AssetStudio var index = curveIndex; ReadCurveData(iAnim, m_ClipBindingConstant, index, time, values, (int)frameOffset, ref curveIndex); } - + } } for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++) @@ -906,9 +908,9 @@ namespace AssetStudio for (int curveIndex = 0; curveIndex < frame.keyList.Length;) { var index = frame.keyList[curveIndex].index; - if (Game.Name != "SR_CB2" && Game.Name != "SR_CB3") + if (!Game.Type.IsSRGroup()) index += (int)aclCount; - ReadCurveData(iAnim, m_ClipBindingConstant, (int)index, frame.time, streamedValues, 0, ref curveIndex); + ReadCurveData(iAnim, m_ClipBindingConstant, index, frame.time, streamedValues, 0, ref curveIndex); } } var m_DenseClip = m_Clip.m_DenseClip; @@ -920,12 +922,12 @@ namespace AssetStudio for (int curveIndex = 0; curveIndex < m_DenseClip.m_CurveCount;) { var index = streamCount + curveIndex; - if (Game.Name != "SR_CB2" && Game.Name != "SR_CB3") - index += aclCount; + if (!Game.Type.IsSRGroup()) + index += (int)aclCount; ReadCurveData(iAnim, m_ClipBindingConstant, (int)index, time, m_DenseClip.m_SampleArray, (int)frameOffset, ref curveIndex); } } - if (m_ACLClip.m_CurveCount != 0 && Game.Name == "SR_CB2" && Game.Name != "SR_CB3") + if (!m_ACLClip.m_ClipData.IsNullOrEmpty() && Game.Type.IsSRGroup()) { m_ACLClip.ProcessSR(out var values, out var times); for (int frameIndex = 0; frameIndex < times.Length; frameIndex++) @@ -1037,6 +1039,7 @@ namespace AssetStudio curveIndex++; } } + private string GetPathFromHash(uint hash) { bonePathHash.TryGetValue(hash, out var boneName); @@ -1054,12 +1057,18 @@ namespace AssetStudio private void CreateBonePathHash(Transform m_Transform) { var name = GetTransformPathByFather(m_Transform); - bonePathHash[CRC.CalculateDigestUTF8(name)] = name; + var crc = new SevenZip.CRC(); + var bytes = Encoding.UTF8.GetBytes(name); + crc.Update(bytes, 0, (uint)bytes.Length); + bonePathHash[crc.GetDigest()] = name; int index; while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0) { name = name.Substring(index + 1); - bonePathHash[CRC.CalculateDigestUTF8(name)] = name; + crc = new SevenZip.CRC(); + bytes = Encoding.UTF8.GetBytes(name); + crc.Update(bytes, 0, (uint)bytes.Length); + bonePathHash[crc.GetDigest()] = name; } foreach (var pptr in m_Transform.m_Children) { diff --git a/AssetStudioUtility/ShaderConverter.cs b/AssetStudioUtility/ShaderConverter.cs index f267644..767a2d3 100644 --- a/AssetStudioUtility/ShaderConverter.cs +++ b/AssetStudioUtility/ShaderConverter.cs @@ -16,7 +16,7 @@ namespace AssetStudio { var decompressedBytes = new byte[shader.decompressedSize]; LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes); - using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + using (var blobReader = new EndianBinaryReader(new MemoryStream(decompressedBytes), EndianType.LittleEndian)) { var program = new ShaderProgram(blobReader, shader.version); program.Read(blobReader, 0); @@ -44,7 +44,7 @@ namespace AssetStudio var compressedLength = shader.compressedLengths[i][j]; var decompressedLength = shader.decompressedLengths[i][j]; var decompressedBytes = new byte[decompressedLength]; - if (game.Name == "GI" || game.Name == "GI_CB2" || game.Name == "GI_CB3") + if (game.Type.IsGISubGroup()) { Buffer.BlockCopy(shader.compressedBlob, (int)offset, decompressedBytes, 0, (int)decompressedLength); } @@ -52,7 +52,7 @@ namespace AssetStudio { LZ4Codec.Decode(shader.compressedBlob, (int)offset, (int)compressedLength, decompressedBytes, 0, (int)decompressedLength); } - using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + using (var blobReader = new EndianBinaryReader(new MemoryStream(decompressedBytes), EndianType.LittleEndian)) { if (j == 0) { @@ -878,7 +878,7 @@ namespace AssetStudio public int Length; public int Segment; - public ShaderSubProgramEntry(BinaryReader reader, int[] version) + public ShaderSubProgramEntry(EndianBinaryReader reader, int[] version) { Offset = reader.ReadInt32(); Length = reader.ReadInt32(); @@ -894,7 +894,7 @@ namespace AssetStudio public ShaderSubProgramEntry[] entries; public ShaderSubProgram[] m_SubPrograms; - public ShaderProgram(BinaryReader reader, int[] version) + public ShaderProgram(EndianBinaryReader reader, int[] version) { var subProgramsCapacity = reader.ReadInt32(); entries = new ShaderSubProgramEntry[subProgramsCapacity]; @@ -905,7 +905,7 @@ namespace AssetStudio m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; } - public void Read(BinaryReader reader, int segment) + public void Read(EndianBinaryReader reader, int segment) { for (int i = 0; i < entries.Length; i++) { @@ -938,7 +938,7 @@ namespace AssetStudio public string[] m_LocalKeywords; public byte[] m_ProgramCode; - public ShaderSubProgram(BinaryReader reader) + public ShaderSubProgram(EndianBinaryReader reader) { //LoadGpuProgramFromData //201509030 - Unity 5.3 @@ -1049,7 +1049,7 @@ namespace AssetStudio } case ShaderGpuProgramType.MetalVS: case ShaderGpuProgramType.MetalFS: - using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode))) + using (var reader = new EndianBinaryReader(new MemoryStream(m_ProgramCode), EndianType.LittleEndian)) { var fourCC = reader.ReadUInt32(); if (fourCC == 0xf00dcafe) diff --git a/AssetStudioUtility/SpriteHelper.cs b/AssetStudioUtility/SpriteHelper.cs index 5002967..7b30d9c 100644 --- a/AssetStudioUtility/SpriteHelper.cs +++ b/AssetStudioUtility/SpriteHelper.cs @@ -139,9 +139,9 @@ namespace AssetStudio var m_VertexData = m_RD.m_VertexData; var m_Channel = m_VertexData.m_Channels[0]; //kShaderChannelVertex var m_Stream = m_VertexData.m_Streams[m_Channel.stream]; - using (var vertexReader = new BinaryReader(new MemoryStream(m_VertexData.m_DataSize))) + using (var vertexReader = new EndianBinaryReader(new MemoryStream(m_VertexData.m_DataSize), EndianType.LittleEndian)) { - using (var indexReader = new BinaryReader(new MemoryStream(m_RD.m_IndexBuffer))) + using (var indexReader = new EndianBinaryReader(new MemoryStream(m_RD.m_IndexBuffer), EndianType.LittleEndian)) { foreach (var subMesh in m_RD.m_SubMeshes) { diff --git a/AssetStudioUtility/Texture2DConverter.cs b/AssetStudioUtility/Texture2DConverter.cs index 8baada4..0e38719 100644 --- a/AssetStudioUtility/Texture2DConverter.cs +++ b/AssetStudioUtility/Texture2DConverter.cs @@ -12,7 +12,7 @@ namespace AssetStudio private TextureFormat m_TextureFormat; private int[] version; private BuildTarget platform; - private int outputSize; + private int outPutSize; public Texture2DConverter(Texture2D m_Texture2D) { @@ -22,7 +22,7 @@ namespace AssetStudio m_TextureFormat = m_Texture2D.m_TextureFormat; version = m_Texture2D.version; platform = m_Texture2D.platform; - outputSize = m_Width * m_Height * 4; + outPutSize = m_Width * m_Height * 4; } public bool DecodeTexture2D(byte[] bytes) @@ -57,7 +57,7 @@ namespace AssetStudio flag = DecodeRGB565(buff, bytes); break; case TextureFormat.R16: //test pass - case TextureFormat.R16_2: //test pass + case TextureFormat.R16_Alt: //test pass flag = DecodeR16(buff, bytes); break; case TextureFormat.DXT1: //test pass @@ -272,7 +272,7 @@ namespace AssetStudio private bool DecodeRGBA32(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = image_data[i + 2]; buff[i + 1] = image_data[i + 1]; @@ -284,7 +284,7 @@ namespace AssetStudio private bool DecodeARGB32(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = image_data[i + 3]; buff[i + 1] = image_data[i + 2]; @@ -351,7 +351,7 @@ namespace AssetStudio private bool DecodeBGRA32(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = image_data[i]; buff[i + 1] = image_data[i + 1]; @@ -363,7 +363,7 @@ namespace AssetStudio private bool DecodeRHalf(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = 0; buff[i + 1] = 0; @@ -375,7 +375,7 @@ namespace AssetStudio private bool DecodeRGHalf(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = 0; buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f); @@ -387,7 +387,7 @@ namespace AssetStudio private bool DecodeRGBAHalf(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f); buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f); @@ -399,7 +399,7 @@ namespace AssetStudio private bool DecodeRFloat(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = 0; buff[i + 1] = 0; @@ -411,7 +411,7 @@ namespace AssetStudio private bool DecodeRGFloat(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = 0; buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f); @@ -423,7 +423,7 @@ namespace AssetStudio private bool DecodeRGBAFloat(byte[] image_data, byte[] buff) { - for (var i = 0; i < buff.Length; i += 4) + for (var i = 0; i < outPutSize; i += 4) { buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f); buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f); @@ -471,7 +471,7 @@ namespace AssetStudio private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff) { - for (var i = 0; i < outputSize; i += 4) + for (var i = 0; i < outPutSize; i += 4) { var n = BitConverter.ToInt32(image_data, i); var scale = n >> 27 & 0x1f; @@ -594,7 +594,7 @@ namespace AssetStudio private bool DecodeRG16(byte[] image_data, byte[] buff) { var size = m_Width * m_Height; - for (var i = 0; i < size; i += 2) + for (var i = 0; i < size; i++) { buff[i * 4] = 0; //B buff[i * 4 + 1] = image_data[i * 2 + 1];//G @@ -617,49 +617,6 @@ namespace AssetStudio return true; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static byte DownScaleFrom16BitTo8Bit(ushort component) - { - return (byte)(((component * 255) + 32895) >> 16); - } - - private bool DecodeRG32(byte[] image_data, byte[] buff) - { - for (var i = 0; i < outputSize; i += 4) - { - buff[i] = 0; //b - buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i + 2)); //g - buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i)); //r - buff[i + 3] = byte.MaxValue; //a - } - return true; - } - - private bool DecodeRGB48(byte[] image_data, byte[] buff) - { - var size = m_Width * m_Height; - for (var i = 0; i < size; i++) - { - buff[i * 4] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 4)); //b - buff[i * 4 + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 2)); //g - buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6)); //r - buff[i * 4 + 3] = byte.MaxValue; //a - } - return true; - } - - private bool DecodeRGBA64(byte[] image_data, byte[] buff) - { - for (var i = 0; i < outputSize; i += 4) - { - buff[i] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 4)); //b - buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 2)); //g - buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r - buff[i + 3] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 6)); //a - } - return true; - } - private bool DecodeETC1Crunched(byte[] image_data, byte[] buff) { if (UnpackCrunch(image_data, out var result)) @@ -684,6 +641,49 @@ namespace AssetStudio return false; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte DownScaleFrom16BitTo8Bit(ushort component) + { + return (byte)(((component * 255) + 32895) >> 16); + } + + private bool DecodeRG32(byte[] image_data, byte[] buff) + { + for (var i = 0; i < outPutSize; i += 4) + { + buff[i] = 0; //b + buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i + 2)); //g + buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i)); //r + buff[i + 3] = byte.MaxValue; //a + } + return true; + } + + private bool DecodeRGB48(byte[] image_data, byte[] buff) + { + var size = m_Width * m_Height; + for (var i = 0; i < size; i++) + { + buff[i * 4] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 4)); //b + buff[i * 4 + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 2)); //g + buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6)); //r + buff[i * 4 + 3] = byte.MaxValue; //a + } + return true; + } + + private bool DecodeRGBA64(byte[] image_data, byte[] buff) + { + for (var i = 0; i < outPutSize; i += 4) + { + buff[i] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 4)); //b + buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 2)); //g + buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r + buff[i + 3] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 6)); //a + } + return true; + } + private bool UnpackCrunch(byte[] image_data, out byte[] result) { if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up diff --git a/Texture2DDecoderNative/Texture2DDecoderNative.rc b/Texture2DDecoderNative/Texture2DDecoderNative.rc deleted file mode 100644 index fa24168..0000000 --- a/Texture2DDecoderNative/Texture2DDecoderNative.rc +++ /dev/null @@ -1,99 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Language neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL -#pragma code_page(65001) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "FileDescription", "Texture2DDecoderNative" - VALUE "FileVersion", "1.0.0.1" - VALUE "InternalName", "Texture2DDecoderNative.dll" - VALUE "LegalCopyright", "Copyright (C) Perfare 2020; Copyright (C) hozuki 2020" - VALUE "OriginalFilename", "Texture2DDecoderNative.dll" - VALUE "ProductName", "Texture2DDecoderNative" - VALUE "ProductVersion", "1.0.0.1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // Language neutral resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj b/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj deleted file mode 100644 index 495ac84..0000000 --- a/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj +++ /dev/null @@ -1,207 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16.0 - Win32Proj - {29356642-c46e-4144-83d8-22dc09d0d7fd} - Texture2DDecoderNative - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - Level3 - true - _T2D_DLL;WIN32;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - stdafx.h - - - Windows - true - false - - - - - Level3 - true - true - true - _T2D_DLL;WIN32;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - stdafx.h - MultiThreaded - - - Windows - true - true - true - false - - - - - Level3 - true - _T2D_DLL;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - stdafx.h - - - Windows - true - false - - - - - Level3 - true - true - true - _T2D_DLL;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - stdafx.h - MultiThreaded - - - Windows - true - true - true - false - - - - - - - - - \ No newline at end of file diff --git a/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj.filters b/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj.filters deleted file mode 100644 index 0d2ff69..0000000 --- a/Texture2DDecoderNative/Texture2DDecoderNative.vcxproj.filters +++ /dev/null @@ -1,113 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - - - - - - 资源文件 - - - \ No newline at end of file diff --git a/Texture2DDecoderNative/astc.cpp b/Texture2DDecoderNative/astc.cpp deleted file mode 100644 index bb4d98a..0000000 --- a/Texture2DDecoderNative/astc.cpp +++ /dev/null @@ -1,1148 +0,0 @@ -#include "astc.h" -#include -#include -#include -#include -#include "color.h" -#include "fp16.h" - -static const int BitReverseTable[] = { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, - 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, - 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, - 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, - 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, - 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, - 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, - 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, - 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, - 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, - 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, - 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, - 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; - -static const int WeightPrecTableA[] = {0, 0, 0, 3, 0, 5, 3, 0, 0, 0, 5, 3, 0, 5, 3, 0}; -static const int WeightPrecTableB[] = {0, 0, 1, 0, 2, 0, 1, 3, 0, 0, 1, 2, 4, 2, 3, 5}; - -static const int CemTableA[] = {0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 0, 0}; -static const int CemTableB[] = {8, 6, 5, 7, 5, 4, 6, 4, 3, 5, 3, 2, 4, 2, 1, 3, 1, 2, 1}; - -static inline uint_fast8_t bit_reverse_u8(const uint_fast8_t c, const int bits) { - return BitReverseTable[c] >> (8 - bits); -} - -static inline uint_fast64_t bit_reverse_u64(const uint_fast64_t d, const int bits) { - uint_fast64_t ret = (uint_fast64_t)BitReverseTable[d & 0xff] << 56 | - (uint_fast64_t)BitReverseTable[d >> 8 & 0xff] << 48 | (uint_fast64_t)BitReverseTable[d >> 16 & 0xff] << 40 | - (uint_fast64_t)BitReverseTable[d >> 24 & 0xff] << 32 | (uint_fast32_t)BitReverseTable[d >> 32 & 0xff] << 24 | - (uint_fast32_t)BitReverseTable[d >> 40 & 0xff] << 16 | (uint_fast16_t)BitReverseTable[d >> 48 & 0xff] << 8 | - BitReverseTable[d >> 56 & 0xff]; - return ret >> (64 - bits); -} - -static inline int getbits(const uint8_t *buf, const int bit, const int len) { - return (*(int *)(buf + bit / 8) >> (bit % 8)) & ((1 << len) - 1); -} - -static inline uint_fast64_t getbits64(const uint8_t *buf, const int bit, const int len) { - uint_fast64_t mask = len == 64 ? 0xffffffffffffffff : (1ull << len) - 1; - if (len < 1) - return 0; - else if (bit >= 64) - return (*(uint_fast64_t *)(buf + 8)) >> (bit - 64) & mask; - else if (bit <= 0) - return (*(uint_fast64_t *)buf) << -bit & mask; - else if (bit + len <= 64) - return (*(uint_fast64_t *)buf) >> bit & mask; - else - return ((*(uint_fast64_t *)buf) >> bit | *(uint_fast64_t *)(buf + 8) << (64 - bit)) & mask; -} - -static inline uint16_t u8ptr_to_u16(const uint8_t *ptr) { - return lton16(*(uint16_t *)ptr); -} - -static inline uint_fast8_t clamp(const int n) { - return n < 0 ? 0 : n > 255 ? 255 : n; -} - -static inline void bit_transfer_signed(int *a, int *b) { - *b = (*b >> 1) | (*a & 0x80); - *a = (*a >> 1) & 0x3f; - if (*a & 0x20) - *a -= 0x40; -} - -static inline void set_endpoint(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) { - endpoint[0] = r1; - endpoint[1] = g1; - endpoint[2] = b1; - endpoint[3] = a1; - endpoint[4] = r2; - endpoint[5] = g2; - endpoint[6] = b2; - endpoint[7] = a2; -} - -static inline void set_endpoint_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) { - endpoint[0] = clamp(r1); - endpoint[1] = clamp(g1); - endpoint[2] = clamp(b1); - endpoint[3] = clamp(a1); - endpoint[4] = clamp(r2); - endpoint[5] = clamp(g2); - endpoint[6] = clamp(b2); - endpoint[7] = clamp(a2); -} - -static inline void set_endpoint_blue(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) { - endpoint[0] = (r1 + b1) >> 1; - endpoint[1] = (g1 + b1) >> 1; - endpoint[2] = b1; - endpoint[3] = a1; - endpoint[4] = (r2 + b2) >> 1; - endpoint[5] = (g2 + b2) >> 1; - endpoint[6] = b2; - endpoint[7] = a2; -} - -static inline void set_endpoint_blue_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, - int a2) { - endpoint[0] = clamp((r1 + b1) >> 1); - endpoint[1] = clamp((g1 + b1) >> 1); - endpoint[2] = clamp(b1); - endpoint[3] = clamp(a1); - endpoint[4] = clamp((r2 + b2) >> 1); - endpoint[5] = clamp((g2 + b2) >> 1); - endpoint[6] = clamp(b2); - endpoint[7] = clamp(a2); -} - -static inline uint_fast16_t clamp_hdr(const int n) { - return n < 0 ? 0 : n > 0xfff ? 0xfff : n; -} - -static inline void set_endpoint_hdr(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) { - endpoint[0] = r1; - endpoint[1] = g1; - endpoint[2] = b1; - endpoint[3] = a1; - endpoint[4] = r2; - endpoint[5] = g2; - endpoint[6] = b2; - endpoint[7] = a2; -} - -static inline void set_endpoint_hdr_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, - int a2) { - endpoint[0] = clamp_hdr(r1); - endpoint[1] = clamp_hdr(g1); - endpoint[2] = clamp_hdr(b1); - endpoint[3] = clamp_hdr(a1); - endpoint[4] = clamp_hdr(r2); - endpoint[5] = clamp_hdr(g2); - endpoint[6] = clamp_hdr(b2); - endpoint[7] = clamp_hdr(a2); -} - -typedef uint_fast8_t (*t_select_folor_func_ptr)(int, int, int); - -static uint_fast8_t select_color(int v0, int v1, int weight) { - return ((((v0 << 8 | v0) * (64 - weight) + (v1 << 8 | v1) * weight + 32) >> 6) * 255 + 32768) / 65536; -} - -static uint_fast8_t select_color_hdr(int v0, int v1, int weight) { - uint16_t c = ((v0 << 4) * (64 - weight) + (v1 << 4) * weight + 32) >> 6; - uint16_t m = c & 0x7ff; - if (m < 512) - m *= 3; - else if (m < 1536) - m = 4 * m - 512; - else - m = 5 * m - 2048; - float f = fp16_ieee_to_fp32_value((c >> 1 & 0x7c00) | m >> 3); - return isfinite(f) ? clamp(roundf(f * 255)) : 255; -} - -static inline uint8_t f32_to_u8(const float f) { - float c = roundf(f * 255); - if (c < 0) - return 0; - else if (c > 255) - return 255; - else - return c; -} - -static inline uint8_t f16ptr_to_u8(const uint8_t *ptr) { - return f32_to_u8(fp16_ieee_to_fp32_value(lton16(*(uint16_t *)ptr))); -} - -typedef struct { - int bw; - int bh; - int width; - int height; - int part_num; - int dual_plane; - int plane_selector; - int weight_range; - int weight_num; - int cem[4]; - int cem_range; - int endpoint_value_num; - int endpoints[4][8]; - int weights[144][2]; - int partition[144]; -} BlockData; - -typedef struct { - int bits; - int nonbits; -} IntSeqData; - -void decode_intseq(const uint8_t *buf, int offset, const int a, const int b, const int count, const int reverse, - IntSeqData *out) { - static int mt[] = {0, 2, 4, 5, 7}; - static int mq[] = {0, 3, 5}; - static int TritsTable[5][256] = { - {0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, - 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, - 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, - 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, - 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, - 1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, - 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2}, - {0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, - 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, - 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, - 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, - 2, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1}, - {0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, - 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, - 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, - 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, - 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, - 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, - 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}}; - static int QuintsTable[3][128] = { - {0, 1, 2, 3, 4, 0, 4, 4, 0, 1, 2, 3, 4, 1, 4, 4, 0, 1, 2, 3, 4, 2, 4, 4, 0, 1, 2, 3, 4, 3, 4, 4, - 0, 1, 2, 3, 4, 0, 4, 0, 0, 1, 2, 3, 4, 1, 4, 1, 0, 1, 2, 3, 4, 2, 4, 2, 0, 1, 2, 3, 4, 3, 4, 3, - 0, 1, 2, 3, 4, 0, 2, 3, 0, 1, 2, 3, 4, 1, 2, 3, 0, 1, 2, 3, 4, 2, 2, 3, 0, 1, 2, 3, 4, 3, 2, 3, - 0, 1, 2, 3, 4, 0, 0, 1, 0, 1, 2, 3, 4, 1, 0, 1, 0, 1, 2, 3, 4, 2, 0, 1, 0, 1, 2, 3, 4, 3, 0, 1}, - {0, 0, 0, 0, 0, 4, 4, 4, 1, 1, 1, 1, 1, 4, 4, 4, 2, 2, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 3, 4, 4, 4, - 0, 0, 0, 0, 0, 4, 0, 4, 1, 1, 1, 1, 1, 4, 1, 4, 2, 2, 2, 2, 2, 4, 2, 4, 3, 3, 3, 3, 3, 4, 3, 4, - 0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3, - 0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3}, - {0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 3, 4, - 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, - 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, - 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4}}; - - if (count <= 0) - return; - - int n = 0; - - if (a == 3) { - int mask = (1 << b) - 1; - int block_count = (count + 4) / 5; - int last_block_count = (count + 4) % 5 + 1; - int block_size = 8 + 5 * b; - int last_block_size = (block_size * last_block_count + 4) / 5; - - if (reverse) { - for (int i = 0, p = offset; i < block_count; i++, p -= block_size) { - int now_size = (i < block_count - 1) ? block_size : last_block_size; - uint_fast64_t d = bit_reverse_u64(getbits64(buf, p - now_size, now_size), now_size); - int x = - (d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80); - for (int j = 0; j < 5 && n < count; j++, n++) - out[n] = { static_cast(d >> (mt[j] + b * j) & mask), TritsTable[j][x]}; - } - } else { - for (int i = 0, p = offset; i < block_count; i++, p += block_size) { - uint_fast64_t d = getbits64(buf, p, (i < block_count - 1) ? block_size : last_block_size); - int x = - (d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80); - for (int j = 0; j < 5 && n < count; j++, n++) - out[n] = { static_cast(d >> (mt[j] + b * j) & mask), TritsTable[j][x]}; - } - } - } else if (a == 5) { - int mask = (1 << b) - 1; - int block_count = (count + 2) / 3; - int last_block_count = (count + 2) % 3 + 1; - int block_size = 7 + 3 * b; - int last_block_size = (block_size * last_block_count + 2) / 3; - - if (reverse) { - for (int i = 0, p = offset; i < block_count; i++, p -= block_size) { - int now_size = (i < block_count - 1) ? block_size : last_block_size; - uint_fast64_t d = bit_reverse_u64(getbits64(buf, p - now_size, now_size), now_size); - int x = (d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60); - for (int j = 0; j < 3 && n < count; j++, n++) - out[n] = { static_cast(d >> (mq[j] + b * j) & mask), QuintsTable[j][x]}; - } - } else { - for (int i = 0, p = offset; i < block_count; i++, p += block_size) { - uint_fast64_t d = getbits64(buf, p, (i < block_count - 1) ? block_size : last_block_size); - int x = (d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60); - for (int j = 0; j < 3 && n < count; j++, n++) - out[n] = { static_cast(d >> (mq[j] + b * j) & mask), QuintsTable[j][x]}; - } - } - } else { - if (reverse) - for (int p = offset - b; n < count; n++, p -= b) - out[n] = {bit_reverse_u8(getbits(buf, p, b), b), 0}; - else - for (int p = offset; n < count; n++, p += b) - out[n] = {getbits(buf, p, b), 0}; - } -} - -void decode_block_params(const uint8_t *buf, BlockData *block_data) { - block_data->dual_plane = !!(buf[1] & 4); - block_data->weight_range = (buf[0] >> 4 & 1) | (buf[1] << 2 & 8); - - if (buf[0] & 3) { - block_data->weight_range |= buf[0] << 1 & 6; - switch (buf[0] & 0xc) { - case 0: - block_data->width = (u8ptr_to_u16(buf) >> 7 & 3) + 4; - block_data->height = (buf[0] >> 5 & 3) + 2; - break; - case 4: - block_data->width = (u8ptr_to_u16(buf) >> 7 & 3) + 8; - block_data->height = (buf[0] >> 5 & 3) + 2; - break; - case 8: - block_data->width = (buf[0] >> 5 & 3) + 2; - block_data->height = (u8ptr_to_u16(buf) >> 7 & 3) + 8; - break; - case 12: - if (buf[1] & 1) { - block_data->width = (buf[0] >> 7 & 1) + 2; - block_data->height = (buf[0] >> 5 & 3) + 2; - } else { - block_data->width = (buf[0] >> 5 & 3) + 2; - block_data->height = (buf[0] >> 7 & 1) + 6; - } - break; - } - } else { - block_data->weight_range |= buf[0] >> 1 & 6; - switch (u8ptr_to_u16(buf) & 0x180) { - case 0: - block_data->width = 12; - block_data->height = (buf[0] >> 5 & 3) + 2; - break; - case 0x80: - block_data->width = (buf[0] >> 5 & 3) + 2; - block_data->height = 12; - break; - case 0x100: - block_data->width = (buf[0] >> 5 & 3) + 6; - block_data->height = (buf[1] >> 1 & 3) + 6; - block_data->dual_plane = 0; - block_data->weight_range &= 7; - break; - case 0x180: - block_data->width = (buf[0] & 0x20) ? 10 : 6; - block_data->height = (buf[0] & 0x20) ? 6 : 10; - break; - } - } - - block_data->part_num = (buf[1] >> 3 & 3) + 1; - - block_data->weight_num = block_data->width * block_data->height; - if (block_data->dual_plane) - block_data->weight_num *= 2; - - int weight_bits, config_bits, cem_base = 0; - - switch (WeightPrecTableA[block_data->weight_range]) { - case 3: - weight_bits = - block_data->weight_num * WeightPrecTableB[block_data->weight_range] + (block_data->weight_num * 8 + 4) / 5; - break; - case 5: - weight_bits = - block_data->weight_num * WeightPrecTableB[block_data->weight_range] + (block_data->weight_num * 7 + 2) / 3; - break; - default: - weight_bits = block_data->weight_num * WeightPrecTableB[block_data->weight_range]; - } - - if (block_data->part_num == 1) { - block_data->cem[0] = u8ptr_to_u16(buf + 1) >> 5 & 0xf; - config_bits = 17; - } else { - cem_base = u8ptr_to_u16(buf + 2) >> 7 & 3; - if (cem_base == 0) { - int cem = buf[3] >> 1 & 0xf; - for (int i = 0; i < block_data->part_num; i++) - block_data->cem[i] = cem; - config_bits = 29; - } else { - for (int i = 0; i < block_data->part_num; i++) - block_data->cem[i] = ((buf[3] >> (i + 1) & 1) + cem_base - 1) << 2; - switch (block_data->part_num) { - case 2: - block_data->cem[0] |= buf[3] >> 3 & 3; - block_data->cem[1] |= getbits(buf, 126 - weight_bits, 2); - break; - case 3: - block_data->cem[0] |= buf[3] >> 4 & 1; - block_data->cem[0] |= getbits(buf, 122 - weight_bits, 2) & 2; - block_data->cem[1] |= getbits(buf, 124 - weight_bits, 2); - block_data->cem[2] |= getbits(buf, 126 - weight_bits, 2); - break; - case 4: - for (int i = 0; i < 4; i++) - block_data->cem[i] |= getbits(buf, 120 + i * 2 - weight_bits, 2); - break; - } - config_bits = 25 + block_data->part_num * 3; - } - } - - if (block_data->dual_plane) { - config_bits += 2; - block_data->plane_selector = - getbits(buf, cem_base ? 130 - weight_bits - block_data->part_num * 3 : 126 - weight_bits, 2); - } - - int remain_bits = 128 - config_bits - weight_bits; - - block_data->endpoint_value_num = 0; - for (int i = 0; i < block_data->part_num; i++) - block_data->endpoint_value_num += (block_data->cem[i] >> 1 & 6) + 2; - - for (int i = 0, endpoint_bits; i < (int)(sizeof(CemTableA) / sizeof(int)); i++) { - switch (CemTableA[i]) { - case 3: - endpoint_bits = - block_data->endpoint_value_num * CemTableB[i] + (block_data->endpoint_value_num * 8 + 4) / 5; - break; - case 5: - endpoint_bits = - block_data->endpoint_value_num * CemTableB[i] + (block_data->endpoint_value_num * 7 + 2) / 3; - break; - default: - endpoint_bits = block_data->endpoint_value_num * CemTableB[i]; - } - - if (endpoint_bits <= remain_bits) { - block_data->cem_range = i; - break; - } - } -} - -void decode_endpoints_hdr7(int *endpoints, int *v) { - int modeval = (v[2] >> 4 & 0x8) | (v[1] >> 5 & 0x4) | (v[0] >> 6); - int major_component, mode; - if ((modeval & 0xc) != 0xc) { - major_component = modeval >> 2; - mode = modeval & 3; - } else if (modeval != 0xf) { - major_component = modeval & 3; - mode = 4; - } else { - major_component = 0; - mode = 5; - } - int c[] = {v[0] & 0x3f, v[1] & 0x1f, v[2] & 0x1f, v[3] & 0x1f}; - - switch (mode) { - case 0: - c[3] |= v[3] & 0x60; - c[0] |= v[3] >> 1 & 0x40; - c[0] |= v[2] << 1 & 0x80; - c[0] |= v[1] << 3 & 0x300; - c[0] |= v[2] << 5 & 0x400; - c[0] <<= 1; - c[1] <<= 1; - c[2] <<= 1; - c[3] <<= 1; - break; - case 1: - c[1] |= v[1] & 0x20; - c[2] |= v[2] & 0x20; - c[0] |= v[3] >> 1 & 0x40; - c[0] |= v[2] << 1 & 0x80; - c[0] |= v[1] << 2 & 0x100; - c[0] |= v[3] << 4 & 0x600; - c[0] <<= 1; - c[1] <<= 1; - c[2] <<= 1; - c[3] <<= 1; - break; - case 2: - c[3] |= v[3] & 0xe0; - c[0] |= v[2] << 1 & 0xc0; - c[0] |= v[1] << 3 & 0x300; - c[0] <<= 2; - c[1] <<= 2; - c[2] <<= 2; - c[3] <<= 2; - break; - case 3: - c[1] |= v[1] & 0x20; - c[2] |= v[2] & 0x20; - c[3] |= v[3] & 0x60; - c[0] |= v[3] >> 1 & 0x40; - c[0] |= v[2] << 1 & 0x80; - c[0] |= v[1] << 2 & 0x100; - c[0] <<= 3; - c[1] <<= 3; - c[2] <<= 3; - c[3] <<= 3; - break; - case 4: - c[1] |= v[1] & 0x60; - c[2] |= v[2] & 0x60; - c[3] |= v[3] & 0x20; - c[0] |= v[3] >> 1 & 0x40; - c[0] |= v[3] << 1 & 0x80; - c[0] <<= 4; - c[1] <<= 4; - c[2] <<= 4; - c[3] <<= 4; - break; - case 5: - c[1] |= v[1] & 0x60; - c[2] |= v[2] & 0x60; - c[3] |= v[3] & 0x60; - c[0] |= v[3] >> 1 & 0x40; - c[0] <<= 5; - c[1] <<= 5; - c[2] <<= 5; - c[3] <<= 5; - break; - } - if (mode != 5) { - c[1] = c[0] - c[1]; - c[2] = c[0] - c[2]; - } - if (major_component == 1) - set_endpoint_hdr_clamp(endpoints, c[1] - c[3], c[0] - c[3], c[2] - c[3], 0x780, c[1], c[0], c[2], 0x780); - else if (major_component == 2) - set_endpoint_hdr_clamp(endpoints, c[2] - c[3], c[1] - c[3], c[0] - c[3], 0x780, c[2], c[1], c[0], 0x780); - else - set_endpoint_hdr_clamp(endpoints, c[0] - c[3], c[1] - c[3], c[2] - c[3], 0x780, c[0], c[1], c[2], 0x780); -} - -void decode_endpoints_hdr11(int *endpoints, int *v, int alpha1, int alpha2) { - int major_component = (v[4] >> 7) | (v[5] >> 6 & 2); - if (major_component == 3) { - set_endpoint_hdr(endpoints, v[0] << 4, v[2] << 4, v[4] << 5 & 0xfe0, alpha1, v[1] << 4, v[3] << 4, - v[5] << 5 & 0xfe0, alpha2); - return; - } - int mode = (v[1] >> 7) | (v[2] >> 6 & 2) | (v[3] >> 5 & 4); - int va = v[0] | (v[1] << 2 & 0x100); - int vb0 = v[2] & 0x3f, vb1 = v[3] & 0x3f; - int vc = v[1] & 0x3f; - int16_t vd0, vd1; - - switch (mode) { - case 0: - case 2: - vd0 = v[4] & 0x7f; - if (vd0 & 0x40) - vd0 |= 0xff80; - vd1 = v[5] & 0x7f; - if (vd1 & 0x40) - vd1 |= 0xff80; - break; - case 1: - case 3: - case 5: - case 7: - vd0 = v[4] & 0x3f; - if (vd0 & 0x20) - vd0 |= 0xffc0; - vd1 = v[5] & 0x3f; - if (vd1 & 0x20) - vd1 |= 0xffc0; - break; - default: - vd0 = v[4] & 0x1f; - if (vd0 & 0x10) - vd0 |= 0xffe0; - vd1 = v[5] & 0x1f; - if (vd1 & 0x10) - vd1 |= 0xffe0; - break; - } - - switch (mode) { - case 0: - vb0 |= v[2] & 0x40; - vb1 |= v[3] & 0x40; - break; - case 1: - vb0 |= v[2] & 0x40; - vb1 |= v[3] & 0x40; - vb0 |= v[4] << 1 & 0x80; - vb1 |= v[5] << 1 & 0x80; - break; - case 2: - va |= v[2] << 3 & 0x200; - vc |= v[3] & 0x40; - break; - case 3: - va |= v[4] << 3 & 0x200; - vc |= v[5] & 0x40; - vb0 |= v[2] & 0x40; - vb1 |= v[3] & 0x40; - break; - case 4: - va |= v[4] << 4 & 0x200; - va |= v[5] << 5 & 0x400; - vb0 |= v[2] & 0x40; - vb1 |= v[3] & 0x40; - vb0 |= v[4] << 1 & 0x80; - vb1 |= v[5] << 1 & 0x80; - break; - case 5: - va |= v[2] << 3 & 0x200; - va |= v[3] << 4 & 0x400; - vc |= v[5] & 0x40; - vc |= v[4] << 1 & 0x80; - break; - case 6: - va |= v[4] << 4 & 0x200; - va |= v[5] << 5 & 0x400; - va |= v[4] << 5 & 0x800; - vc |= v[5] & 0x40; - vb0 |= v[2] & 0x40; - vb1 |= v[3] & 0x40; - break; - case 7: - va |= v[2] << 3 & 0x200; - va |= v[3] << 4 & 0x400; - va |= v[4] << 5 & 0x800; - vc |= v[5] & 0x40; - break; - } - - int shamt = (mode >> 1) ^ 3; - va <<= shamt; - vb0 <<= shamt; - vb1 <<= shamt; - vc <<= shamt; - int mult = 1 << shamt; - vd0 *= mult; - vd1 *= mult; - - if (major_component == 1) - set_endpoint_hdr_clamp(endpoints, va - vb0 - vc - vd0, va - vc, va - vb1 - vc - vd1, alpha1, va - vb0, va, - va - vb1, alpha2); - else if (major_component == 2) - set_endpoint_hdr_clamp(endpoints, va - vb1 - vc - vd1, va - vb0 - vc - vd0, va - vc, alpha1, va - vb1, va - vb0, - va, alpha2); - else - set_endpoint_hdr_clamp(endpoints, va - vc, va - vb0 - vc - vd0, va - vb1 - vc - vd1, alpha1, va, va - vb0, - va - vb1, alpha2); -} - -void decode_endpoints(const uint8_t *buf, BlockData *data) { - static const int TritsTable[] = {0, 204, 93, 44, 22, 11, 5}; - static const int QuintsTable[] = {0, 113, 54, 26, 13, 6}; - IntSeqData seq[32]; - int ev[32]; - decode_intseq(buf, data->part_num == 1 ? 17 : 29, CemTableA[data->cem_range], CemTableB[data->cem_range], - data->endpoint_value_num, 0, seq); - - switch (CemTableA[data->cem_range]) { - case 3: - for (int i = 0, b, c = TritsTable[CemTableB[data->cem_range]]; i < data->endpoint_value_num; i++) { - int a = (seq[i].bits & 1) * 0x1ff; - int x = seq[i].bits >> 1; - switch (CemTableB[data->cem_range]) { - case 1: - b = 0; - break; - case 2: - b = 0b100010110 * x; - break; - case 3: - b = x << 7 | x << 2 | x; - break; - case 4: - b = x << 6 | x; - break; - case 5: - b = x << 5 | x >> 2; - break; - case 6: - b = x << 4 | x >> 4; - break; - } - ev[i] = (a & 0x80) | ((seq[i].nonbits * c + b) ^ a) >> 2; - } - break; - case 5: - for (int i = 0, b, c = QuintsTable[CemTableB[data->cem_range]]; i < data->endpoint_value_num; i++) { - int a = (seq[i].bits & 1) * 0x1ff; - int x = seq[i].bits >> 1; - switch (CemTableB[data->cem_range]) { - case 1: - b = 0; - break; - case 2: - b = 0b100001100 * x; - break; - case 3: - b = x << 7 | x << 1 | x >> 1; - break; - case 4: - b = x << 6 | x >> 1; - break; - case 5: - b = x << 5 | x >> 3; - break; - } - ev[i] = (a & 0x80) | ((seq[i].nonbits * c + b) ^ a) >> 2; - } - break; - default: - switch (CemTableB[data->cem_range]) { - case 1: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits * 0xff; - break; - case 2: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits * 0x55; - break; - case 3: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits << 5 | seq[i].bits << 2 | seq[i].bits >> 1; - break; - case 4: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits << 4 | seq[i].bits; - break; - case 5: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits << 3 | seq[i].bits >> 2; - break; - case 6: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits << 2 | seq[i].bits >> 4; - break; - case 7: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits << 1 | seq[i].bits >> 6; - break; - case 8: - for (int i = 0; i < data->endpoint_value_num; i++) - ev[i] = seq[i].bits; - break; - } - } - - int *v = ev; - for (int cem = 0; cem < data->part_num; v += (data->cem[cem] / 4 + 1) * 2, cem++) { - switch (data->cem[cem]) { - case 0: - set_endpoint(data->endpoints[cem], v[0], v[0], v[0], 255, v[1], v[1], v[1], 255); - break; - case 1: { - int l0 = (v[0] >> 2) | (v[1] & 0xc0); - int l1 = clamp(l0 + (v[1] & 0x3f)); - set_endpoint(data->endpoints[cem], l0, l0, l0, 255, l1, l1, l1, 255); - } break; - case 2: { - int y0, y1; - if (v[0] <= v[1]) { - y0 = v[0] << 4; - y1 = v[1] << 4; - } else { - y0 = (v[1] << 4) + 8; - y1 = (v[0] << 4) - 8; - } - set_endpoint_hdr(data->endpoints[cem], y0, y0, y0, 0x780, y1, y1, y1, 0x780); - } break; - case 3: { - int y0, d; - if (v[0] & 0x80) { - y0 = (v[1] & 0xe0) << 4 | (v[0] & 0x7f) << 2; - d = (v[1] & 0x1f) << 2; - } else { - y0 = (v[1] & 0xf0) << 4 | (v[0] & 0x7f) << 1; - d = (v[1] & 0x0f) << 1; - } - int y1 = clamp_hdr(y0 + d); - set_endpoint_hdr(data->endpoints[cem], y0, y0, y0, 0x780, y1, y1, y1, 0x780); - } break; - case 4: - set_endpoint(data->endpoints[cem], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[3]); - break; - case 5: - bit_transfer_signed(&v[1], &v[0]); - bit_transfer_signed(&v[3], &v[2]); - v[1] += v[0]; - set_endpoint_clamp(data->endpoints[cem], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[2] + v[3]); - break; - case 6: - set_endpoint(data->endpoints[cem], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, 255, v[0], v[1], - v[2], 255); - break; - case 7: - decode_endpoints_hdr7(data->endpoints[cem], v); - break; - case 8: - if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5]) - set_endpoint(data->endpoints[cem], v[0], v[2], v[4], 255, v[1], v[3], v[5], 255); - else - set_endpoint_blue(data->endpoints[cem], v[1], v[3], v[5], 255, v[0], v[2], v[4], 255); - break; - case 9: - bit_transfer_signed(&v[1], &v[0]); - bit_transfer_signed(&v[3], &v[2]); - bit_transfer_signed(&v[5], &v[4]); - if (v[1] + v[3] + v[5] >= 0) - set_endpoint_clamp(data->endpoints[cem], v[0], v[2], v[4], 255, v[0] + v[1], v[2] + v[3], v[4] + v[5], - 255); - else - set_endpoint_blue_clamp(data->endpoints[cem], v[0] + v[1], v[2] + v[3], v[4] + v[5], 255, v[0], v[2], - v[4], 255); - break; - case 10: - set_endpoint(data->endpoints[cem], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, v[4], v[0], v[1], - v[2], v[5]); - break; - case 11: - decode_endpoints_hdr11(data->endpoints[cem], v, 0x780, 0x780); - break; - case 12: - if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5]) - set_endpoint(data->endpoints[cem], v[0], v[2], v[4], v[6], v[1], v[3], v[5], v[7]); - else - set_endpoint_blue(data->endpoints[cem], v[1], v[3], v[5], v[7], v[0], v[2], v[4], v[6]); - break; - case 13: - bit_transfer_signed(&v[1], &v[0]); - bit_transfer_signed(&v[3], &v[2]); - bit_transfer_signed(&v[5], &v[4]); - bit_transfer_signed(&v[7], &v[6]); - if (v[1] + v[3] + v[5] >= 0) - set_endpoint_clamp(data->endpoints[cem], v[0], v[2], v[4], v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5], - v[6] + v[7]); - else - set_endpoint_blue_clamp(data->endpoints[cem], v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7], v[0], - v[2], v[4], v[6]); - break; - case 14: - decode_endpoints_hdr11(data->endpoints[cem], v, v[6], v[7]); - break; - case 15: { - int mode = ((v[6] >> 7) & 1) | ((v[7] >> 6) & 2); - v[6] &= 0x7f; - v[7] &= 0x7f; - if (mode == 3) { - decode_endpoints_hdr11(data->endpoints[cem], v, v[6] << 5, v[7] << 5); - } else { - v[6] |= (v[7] << (mode + 1)) & 0x780; - v[7] = ((v[7] & (0x3f >> mode)) ^ (0x20 >> mode)) - (0x20 >> mode); - v[6] <<= 4 - mode; - v[7] <<= 4 - mode; - decode_endpoints_hdr11(data->endpoints[cem], v, v[6], clamp_hdr(v[6] + v[7])); - } - } break; - //default: - // rb_raise(rb_eStandardError, "Unsupported ASTC format"); - } - } -} - -void decode_weights(const uint8_t *buf, BlockData *data) { - IntSeqData seq[128]; - int wv[128] = {}; - decode_intseq(buf, 128, WeightPrecTableA[data->weight_range], WeightPrecTableB[data->weight_range], - data->weight_num, 1, seq); - - if (WeightPrecTableA[data->weight_range] == 0) { - switch (WeightPrecTableB[data->weight_range]) { - case 1: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].bits ? 63 : 0; - break; - case 2: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].bits << 4 | seq[i].bits << 2 | seq[i].bits; - break; - case 3: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].bits << 3 | seq[i].bits; - break; - case 4: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].bits << 2 | seq[i].bits >> 2; - break; - case 5: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].bits << 1 | seq[i].bits >> 4; - break; - } - for (int i = 0; i < data->weight_num; i++) - if (wv[i] > 32) - ++wv[i]; - } else if (WeightPrecTableB[data->weight_range] == 0) { - int s = WeightPrecTableA[data->weight_range] == 3 ? 32 : 16; - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].nonbits * s; - } else { - if (WeightPrecTableA[data->weight_range] == 3) { - switch (WeightPrecTableB[data->weight_range]) { - case 1: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].nonbits * 50; - break; - case 2: - for (int i = 0; i < data->weight_num; i++) { - wv[i] = seq[i].nonbits * 23; - if (seq[i].bits & 2) - wv[i] += 0b1000101; - } - break; - case 3: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].nonbits * 11 + ((seq[i].bits << 4 | seq[i].bits >> 1) & 0b1100011); - break; - } - } else if (WeightPrecTableA[data->weight_range] == 5) { - switch (WeightPrecTableB[data->weight_range]) { - case 1: - for (int i = 0; i < data->weight_num; i++) - wv[i] = seq[i].nonbits * 28; - break; - case 2: - for (int i = 0; i < data->weight_num; i++) { - wv[i] = seq[i].nonbits * 13; - if (seq[i].bits & 2) - wv[i] += 0b1000010; - } - break; - } - } - for (int i = 0; i < data->weight_num; i++) { - int a = (seq[i].bits & 1) * 0x7f; - wv[i] = (a & 0x20) | ((wv[i] ^ a) >> 2); - if (wv[i] > 32) - ++wv[i]; - } - } - - int ds = (1024 + data->bw / 2) / (data->bw - 1); - int dt = (1024 + data->bh / 2) / (data->bh - 1); - int pn = data->dual_plane ? 2 : 1; - - for (int t = 0, i = 0; t < data->bh; t++) { - for (int s = 0; s < data->bw; s++, i++) { - int gs = (ds * s * (data->width - 1) + 32) >> 6; - int gt = (dt * t * (data->height - 1) + 32) >> 6; - int fs = gs & 0xf; - int ft = gt & 0xf; - int v = (gs >> 4) + (gt >> 4) * data->width; - int w11 = (fs * ft + 8) >> 4; - int w10 = ft - w11; - int w01 = fs - w11; - int w00 = 16 - fs - ft + w11; - - for (int p = 0; p < pn; p++) { - int p00 = wv[v * pn + p]; - int p01 = wv[(v + 1) * pn + p]; - int p10 = wv[(v + data->width) * pn + p]; - int p11 = wv[(v + data->width + 1) * pn + p]; - data->weights[i][p] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4; - } - } - } -} - -void select_partition(const uint8_t *buf, BlockData *data) { - int small_block = data->bw * data->bh < 31; - int seed = (*(int *)buf >> 13 & 0x3ff) | (data->part_num - 1) << 10; - - uint32_t rnum = seed; - rnum ^= rnum >> 15; - rnum -= rnum << 17; - rnum += rnum << 7; - rnum += rnum << 4; - rnum ^= rnum >> 5; - rnum += rnum << 16; - rnum ^= rnum >> 7; - rnum ^= rnum >> 3; - rnum ^= rnum << 6; - rnum ^= rnum >> 17; - - int seeds[8]; - for (int i = 0; i < 8; i++) { - seeds[i] = (rnum >> (i * 4)) & 0xF; - seeds[i] *= seeds[i]; - } - - int sh[2] = {seed & 2 ? 4 : 5, data->part_num == 3 ? 6 : 5}; - - if (seed & 1) - for (int i = 0; i < 8; i++) - seeds[i] >>= sh[i % 2]; - else - for (int i = 0; i < 8; i++) - seeds[i] >>= sh[1 - i % 2]; - - if (small_block) { - for (int t = 0, i = 0; t < data->bh; t++) { - for (int s = 0; s < data->bw; s++, i++) { - int x = s << 1; - int y = t << 1; - int a = (seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f; - int b = (seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f; - int c = data->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f; - int d = data->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f; - data->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3; - } - } - } else { - for (int y = 0, i = 0; y < data->bh; y++) { - for (int x = 0; x < data->bw; x++, i++) { - int a = (seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f; - int b = (seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f; - int c = data->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f; - int d = data->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f; - data->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3; - } - } - } -} - -void applicate_color(const BlockData *data, uint32_t *outbuf) { - static const t_select_folor_func_ptr FuncTableC[] = { - select_color, select_color, select_color_hdr, select_color_hdr, select_color, select_color, - select_color, select_color_hdr, select_color, select_color, select_color, select_color_hdr, - select_color, select_color, select_color_hdr, select_color_hdr}; - static const t_select_folor_func_ptr FuncTableA[] = { - select_color, select_color, select_color_hdr, select_color_hdr, select_color, select_color, - select_color, select_color_hdr, select_color, select_color, select_color, select_color_hdr, - select_color, select_color, select_color, select_color_hdr}; - if (data->dual_plane) { - int ps[] = {0, 0, 0, 0}; - ps[data->plane_selector] = 1; - if (data->part_num > 1) { - for (int i = 0; i < data->bw * data->bh; i++) { - int p = data->partition[i]; - uint_fast8_t r = - FuncTableC[data->cem[p]](data->endpoints[p][0], data->endpoints[p][4], data->weights[i][ps[0]]); - uint_fast8_t g = - FuncTableC[data->cem[p]](data->endpoints[p][1], data->endpoints[p][5], data->weights[i][ps[1]]); - uint_fast8_t b = - FuncTableC[data->cem[p]](data->endpoints[p][2], data->endpoints[p][6], data->weights[i][ps[2]]); - uint_fast8_t a = - FuncTableA[data->cem[p]](data->endpoints[p][3], data->endpoints[p][7], data->weights[i][ps[3]]); - outbuf[i] = color(r, g, b, a); - } - } else { - for (int i = 0; i < data->bw * data->bh; i++) { - uint_fast8_t r = - FuncTableC[data->cem[0]](data->endpoints[0][0], data->endpoints[0][4], data->weights[i][ps[0]]); - uint_fast8_t g = - FuncTableC[data->cem[0]](data->endpoints[0][1], data->endpoints[0][5], data->weights[i][ps[1]]); - uint_fast8_t b = - FuncTableC[data->cem[0]](data->endpoints[0][2], data->endpoints[0][6], data->weights[i][ps[2]]); - uint_fast8_t a = - FuncTableA[data->cem[0]](data->endpoints[0][3], data->endpoints[0][7], data->weights[i][ps[3]]); - outbuf[i] = color(r, g, b, a); - } - } - } else if (data->part_num > 1) { - for (int i = 0; i < data->bw * data->bh; i++) { - int p = data->partition[i]; - uint_fast8_t r = - FuncTableC[data->cem[p]](data->endpoints[p][0], data->endpoints[p][4], data->weights[i][0]); - uint_fast8_t g = - FuncTableC[data->cem[p]](data->endpoints[p][1], data->endpoints[p][5], data->weights[i][0]); - uint_fast8_t b = - FuncTableC[data->cem[p]](data->endpoints[p][2], data->endpoints[p][6], data->weights[i][0]); - uint_fast8_t a = - FuncTableA[data->cem[p]](data->endpoints[p][3], data->endpoints[p][7], data->weights[i][0]); - outbuf[i] = color(r, g, b, a); - } - } else { - for (int i = 0; i < data->bw * data->bh; i++) { - uint_fast8_t r = - FuncTableC[data->cem[0]](data->endpoints[0][0], data->endpoints[0][4], data->weights[i][0]); - uint_fast8_t g = - FuncTableC[data->cem[0]](data->endpoints[0][1], data->endpoints[0][5], data->weights[i][0]); - uint_fast8_t b = - FuncTableC[data->cem[0]](data->endpoints[0][2], data->endpoints[0][6], data->weights[i][0]); - uint_fast8_t a = - FuncTableA[data->cem[0]](data->endpoints[0][3], data->endpoints[0][7], data->weights[i][0]); - outbuf[i] = color(r, g, b, a); - } - } -} - -void decode_block(const uint8_t *buf, const int bw, const int bh, uint32_t *outbuf) { - if (buf[0] == 0xfc && (buf[1] & 1) == 1) { - uint_fast32_t c; - if (buf[1] & 2) - c = color(f16ptr_to_u8(buf + 8), f16ptr_to_u8(buf + 10), f16ptr_to_u8(buf + 12), f16ptr_to_u8(buf + 14)); - else - c = color(buf[9], buf[11], buf[13], buf[15]); - for (int i = 0; i < bw * bh; i++) - outbuf[i] = c; - } else if (((buf[0] & 0xc3) == 0xc0 && (buf[1] & 1) == 1) || (buf[0] & 0xf) == 0) { - uint_fast32_t c = color(255, 0, 255, 255); - for (int i = 0; i < bw * bh; i++) - outbuf[i] = c; - } else { - BlockData block_data; - block_data.bw = bw; - block_data.bh = bh; - decode_block_params(buf, &block_data); - decode_endpoints(buf, &block_data); - decode_weights(buf, &block_data); - if (block_data.part_num > 1) - select_partition(buf, &block_data); - applicate_color(&block_data, outbuf); - } -} - -int decode_astc(const uint8_t *data, const long w, const long h, const int bw, const int bh, uint32_t *image) { - const long num_blocks_x = (w + bw - 1) / bw; - const long num_blocks_y = (h + bh - 1) / bh; - uint32_t buffer[144]; - const uint8_t *d = data; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, d += 16) { - decode_block(d, bw, bh, buffer); - copy_block_buffer(bx, by, w, h, bw, bh, buffer, image); - } - } - return 1; -} diff --git a/Texture2DDecoderNative/astc.h b/Texture2DDecoderNative/astc.h deleted file mode 100644 index 3fa2cfc..0000000 --- a/Texture2DDecoderNative/astc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ASTC_H -#define ASTC_H - -#include - -int decode_astc(const uint8_t *, const long, const long, const int, const int, uint32_t *); - -#endif /* end of include guard: ASTC_H */ diff --git a/Texture2DDecoderNative/atc.cpp b/Texture2DDecoderNative/atc.cpp deleted file mode 100644 index 9f3e209..0000000 --- a/Texture2DDecoderNative/atc.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "bcn.h" -#include "atc.h" -#include "color.h" -#include - -static uint8_t expand_quantized(uint8_t v, int bits) { - v = v << (8 - bits); - return v | (v >> bits); -} - -void decode_atc_block(const uint8_t* _src, uint32_t* _dst) -{ - uint8_t colors[4 * 4]; - - uint32_t c0 = _src[0] | (_src[1] << 8); - uint32_t c1 = _src[2] | (_src[3] << 8); - - if (0 == (c0 & 0x8000)) - { - colors[0] = expand_quantized((c0 >> 0) & 0x1f, 5); - colors[1] = expand_quantized((c0 >> 5) & 0x1f, 5); - colors[2] = expand_quantized((c0 >> 10) & 0x1f, 5); - - colors[12] = expand_quantized((c1 >> 0) & 0x1f, 5); - colors[13] = expand_quantized((c1 >> 5) & 0x3f, 6); - colors[14] = expand_quantized((c1 >> 11) & 0x1f, 5); - - colors[4] = (5 * colors[0] + 3 * colors[12]) / 8; - colors[5] = (5 * colors[1] + 3 * colors[13]) / 8; - colors[6] = (5 * colors[2] + 3 * colors[14]) / 8; - - colors[8] = (3 * colors[0] + 5 * colors[12]) / 8; - colors[9] = (3 * colors[1] + 5 * colors[13]) / 8; - colors[10] = (3 * colors[2] + 5 * colors[14]) / 8; - } - else - { - colors[0] = 0; - colors[1] = 0; - colors[2] = 0; - - colors[8] = expand_quantized((c0 >> 0) & 0x1f, 5); - colors[9] = expand_quantized((c0 >> 5) & 0x1f, 5); - colors[10] = expand_quantized((c0 >> 10) & 0x1f, 5); - - colors[12] = expand_quantized((c1 >> 0) & 0x1f, 5); - colors[13] = expand_quantized((c1 >> 5) & 0x3f, 6); - colors[14] = expand_quantized((c1 >> 11) & 0x1f, 5); - - colors[4] = std::max(0, colors[8] - colors[12] / 4); - colors[5] = std::max(0, colors[9] - colors[13] / 4); - colors[6] = std::max(0, colors[10] - colors[14] / 4); - } - - for (uint32_t i = 0, next = 8 * 4; i < 16; i += 1, next += 2) - { - int32_t idx = ((_src[next >> 3] >> (next & 7)) & 3) * 4; - _dst[i] = color(colors[idx + 2], colors[idx + 1], colors[idx + 0], 255); - } -} - -int decode_atc_rgb4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 8) { - decode_atc_block(data, buffer); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} - -int decode_atc_rgba8(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) { - decode_atc_block(data + 8, buffer); - decode_bc3_alpha(data, buffer, 3); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} \ No newline at end of file diff --git a/Texture2DDecoderNative/atc.h b/Texture2DDecoderNative/atc.h deleted file mode 100644 index 4b2c1bb..0000000 --- a/Texture2DDecoderNative/atc.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include - -int decode_atc_rgb4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); -int decode_atc_rgba8(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); \ No newline at end of file diff --git a/Texture2DDecoderNative/bcn.cpp b/Texture2DDecoderNative/bcn.cpp deleted file mode 100644 index 1dc0d88..0000000 --- a/Texture2DDecoderNative/bcn.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -#include "bcn.h" -#include -#include -#include -#include "color.h" -#include "fp16.h" - -static inline void decode_bc1_block(const uint8_t* data, uint32_t* outbuf) { - uint8_t r0, g0, b0, r1, g1, b1; - int q0 = *(uint16_t*)(data); - int q1 = *(uint16_t*)(data + 2); - rgb565_le(q0, &r0, &g0, &b0); - rgb565_le(q1, &r1, &g1, &b1); - uint_fast32_t c[4] = { color(r0, g0, b0, 255), color(r1, g1, b1, 255) }; - if (q0 > q1) { - c[2] = color((r0 * 2 + r1) / 3, (g0 * 2 + g1) / 3, (b0 * 2 + b1) / 3, 255); - c[3] = color((r0 + r1 * 2) / 3, (g0 + g1 * 2) / 3, (b0 + b1 * 2) / 3, 255); - } - else { - c[2] = color((r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2, 255); - c[3] = color(0, 0, 0, 255); - } - uint_fast32_t d = lton32(*(uint32_t*)(data + 4)); - for (int i = 0; i < 16; i++, d >>= 2) - outbuf[i] = c[d & 3]; -} - -int decode_bc1(const uint8_t* data, const long w, const long h, uint32_t* image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - const uint8_t* d = data; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, d += 8) { - decode_bc1_block(d, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -void decode_bc3_alpha(const uint8_t* data, uint32_t* outbuf, int channel) { - uint_fast8_t a[8] = { data[0], data[1] }; - if (a[0] > a[1]) { - a[2] = (a[0] * 6 + a[1]) / 7; - a[3] = (a[0] * 5 + a[1] * 2) / 7; - a[4] = (a[0] * 4 + a[1] * 3) / 7; - a[5] = (a[0] * 3 + a[1] * 4) / 7; - a[6] = (a[0] * 2 + a[1] * 5) / 7; - a[7] = (a[0] + a[1] * 6) / 7; - } - else { - a[2] = (a[0] * 4 + a[1]) / 5; - a[3] = (a[0] * 3 + a[1] * 2) / 5; - a[4] = (a[0] * 2 + a[1] * 3) / 5; - a[5] = (a[0] + a[1] * 4) / 5; - a[6] = 0; - a[7] = 255; - } - - uint8_t* dst = (uint8_t*)outbuf; - uint_fast64_t d = lton64(*(uint64_t*)data) >> 16; - for (int i = 0; i < 16; i++, d >>= 3) - dst[i * 4 + channel] = a[d & 7]; -} - -static inline void decode_bc3_block(const uint8_t* data, uint32_t* outbuf) { - decode_bc1_block(data + 8, outbuf); - decode_bc3_alpha(data, outbuf, 3); -} - -int decode_bc3(const uint8_t* data, const long w, const long h, uint32_t* image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - const uint8_t* d = data; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, d += 16) { - decode_bc3_block(d, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -static inline void decode_bc4_block(const uint8_t* data, uint32_t* outbuf) { - decode_bc3_alpha(data, outbuf, 2); -} - -int decode_bc4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t i = 0; i < 16; i++) - buffer[i] = 0xff000000; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 8) { - decode_bc4_block(data, buffer); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} - -static inline void decode_bc5_block(const uint8_t* data, uint32_t* outbuf) { - decode_bc3_alpha(data, outbuf, 2); - decode_bc3_alpha(data + 8, outbuf, 1); -} - -int decode_bc5(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t i = 0; i < 16; i++) - buffer[i] = 0xff000000; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) { - decode_bc5_block(data, buffer); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} - -struct BitReader -{ - BitReader(const uint8_t* _data, uint16_t _bitPos = 0) - : m_data(_data) - , m_bitPos(_bitPos) - { - } - - uint16_t read(uint8_t _numBits) - { - const uint16_t pos = m_bitPos / 8; - const uint16_t shift = m_bitPos & 7; - uint32_t data = 0; - memcpy(&data, &m_data[pos], std::min(4, 16 - pos)); - m_bitPos += _numBits; - return uint16_t((data >> shift) & ((1 << _numBits) - 1)); - } - - uint16_t peek(uint16_t _offset, uint8_t _numBits) - { - const uint16_t bitPos = m_bitPos + _offset; - const uint16_t shift = bitPos & 7; - uint16_t pos = bitPos / 8; - uint32_t data = 0; - memcpy(&data, &m_data[pos], std::min(4, 16 - pos)); - return uint8_t((data >> shift) & ((1 << _numBits) - 1)); - } - - const uint8_t* m_data; - uint16_t m_bitPos; -}; - -static const uint16_t s_bptcP2[] = -{ // 3210 0000000000 1111111111 2222222222 3333333333 - 0xcccc, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 - 0x8888, // 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 - 0xeeee, // 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 - 0xecc8, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 - 0xc880, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 - 0xfeec, // 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 - 0xfec8, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 - 0xec80, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 - 0xc800, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 - 0xffec, // 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - 0xfe80, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 - 0xe800, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 - 0xffe8, // 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - 0xff00, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 - 0xfff0, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - 0xf000, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 - 0xf710, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 - 0x008e, // 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 - 0x7100, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 - 0x08ce, // 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 - 0x008c, // 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 - 0x7310, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 - 0x3100, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 - 0x8cce, // 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 - 0x088c, // 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 - 0x3110, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 - 0x6666, // 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 - 0x366c, // 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 - 0x17e8, // 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 - 0x0ff0, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 - 0x718e, // 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 - 0x399c, // 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 - 0xaaaa, // 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 - 0xf0f0, // 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 - 0x5a5a, // 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 - 0x33cc, // 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 - 0x3c3c, // 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 - 0x55aa, // 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 - 0x9696, // 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 - 0xa55a, // 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 - 0x73ce, // 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 - 0x13c8, // 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 - 0x324c, // 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 - 0x3bdc, // 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 - 0x6996, // 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 - 0xc33c, // 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 - 0x9966, // 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 - 0x0660, // 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 - 0x0272, // 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 - 0x04e4, // 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 - 0x4e40, // 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 - 0x2720, // 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 - 0xc936, // 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 - 0x936c, // 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 - 0x39c6, // 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 - 0x639c, // 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 - 0x9336, // 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 - 0x9cc6, // 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 - 0x817e, // 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 - 0xe718, // 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 - 0xccf0, // 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 - 0x0fcc, // 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 - 0x7744, // 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 - 0xee22, // 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 -}; - -static const uint8_t s_bptcA2[] = -{ - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 2, 8, 2, 2, 8, 8, 15, - 2, 8, 2, 2, 8, 8, 2, 2, - 15, 15, 6, 8, 2, 8, 15, 15, - 2, 8, 2, 2, 2, 15, 15, 6, - 6, 2, 6, 8, 15, 15, 2, 2, - 15, 15, 15, 15, 15, 2, 2, 15, -}; - -static const uint8_t s_bptcFactors[3][16] = -{ - { 0, 21, 43, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 9, 18, 27, 37, 46, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }, -}; - -struct Bc6hModeInfo -{ - uint8_t transformed; - uint8_t partitionBits; - uint8_t endpointBits; - uint8_t deltaBits[3]; -}; - -static const Bc6hModeInfo s_bc6hModeInfo[] = -{ // +--------------------------- transformed - // | +------------------------ partition bits - // | | +--------------------- endpoint bits - // | | | +-------------- delta bits - { 1, 5, 10, { 5, 5, 5 } }, // 00 2-bits - { 1, 5, 7, { 6, 6, 6 } }, // 01 - { 1, 5, 11, { 5, 4, 4 } }, // 00010 5-bits - { 0, 0, 10, { 10, 10, 10 } }, // 00011 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 11, { 4, 5, 4 } }, // 00110 - { 1, 0, 11, { 9, 9, 9 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 11, { 4, 4, 5 } }, // 00010 - { 1, 0, 12, { 8, 8, 8 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 9, { 5, 5, 5 } }, // 00010 - { 1, 0, 16, { 4, 4, 4 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 8, { 6, 5, 5 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 8, { 5, 6, 5 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 1, 5, 8, { 5, 5, 6 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 0, 0, { 0, 0, 0 } }, // - - { 0, 5, 6, { 6, 6, 6 } }, // 00010 - { 0, 0, 0, { 0, 0, 0 } }, // - -}; - -static uint16_t unquantize(uint16_t _value, bool _signed, uint8_t _endpointBits) -{ - const uint16_t maxValue = 1 << (_endpointBits - 1); - - if (_signed) - { - if (_endpointBits >= 16) - { - return _value; - } - - const bool sign = !!(_value & 0x8000); - _value &= 0x7fff; - - uint16_t unq; - - if (0 == _value) - { - unq = 0; - } - else if (_value >= maxValue - 1) - { - unq = 0x7fff; - } - else - { - unq = ((_value << 15) + 0x4000) >> (_endpointBits - 1); - } - - return sign ? -unq : unq; - } - - if (_endpointBits >= 15) - { - return _value; - } - - if (0 == _value) - { - return 0; - } - - if (_value == maxValue) - { - return UINT16_MAX; - } - - return ((_value << 15) + 0x4000) >> (_endpointBits - 1); -} - -static uint16_t finish_unquantize(uint16_t _value, bool _signed) -{ - if (_signed) - { - const uint16_t sign = _value & 0x8000; - _value &= 0x7fff; - - return ((_value * 31) >> 5) | sign; - } - - return (_value * 31) >> 6; -} - -static uint16_t sign_extend(uint16_t _value, uint8_t _numBits) -{ - const uint16_t mask = 1 << (_numBits - 1); - const uint16_t result = (_value ^ mask) - mask; - - return result; -} - -static inline uint8_t f32_to_u8(const float f) { - float c = roundf(f * 255); - if (c < 0) - return 0; - else if (c > 255) - return 255; - else - return c; -} - -static uint8_t half_to_u8(uint16_t h) { - return f32_to_u8(fp16_ieee_to_fp32_value(h)); -} - -static void decode_bc6_block(const uint8_t* _src, uint32_t* _dst, bool _signed) -{ - BitReader bit(_src); - - uint8_t mode = uint8_t(bit.read(2)); - - uint16_t epR[4] = { /* rw, rx, ry, rz */ }; - uint16_t epG[4] = { /* gw, gx, gy, gz */ }; - uint16_t epB[4] = { /* bw, bx, by, bz */ }; - - if (mode & 2) - { - // 5-bit mode - mode |= bit.read(3) << 2; - - if (0 == s_bc6hModeInfo[mode].endpointBits) - { - memset(_dst, 0, 16 * 4); - return; - } - - switch (mode) - { - case 2: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(5) << 0; - epR[0] |= bit.read(1) << 10; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(4) << 0; - epG[0] |= bit.read(1) << 10; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(4) << 0; - epB[0] |= bit.read(1) << 10; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 3; - break; - - case 3: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(10) << 0; - epG[1] |= bit.read(10) << 0; - epB[1] |= bit.read(10) << 0; - break; - - case 6: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(4) << 0; - epR[0] |= bit.read(1) << 10; - epG[3] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(5) << 0; - epG[0] |= bit.read(1) << 10; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(4) << 0; - epB[0] |= bit.read(1) << 10; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(4) << 0; - epB[3] |= bit.read(1) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(4) << 0; - epG[2] |= bit.read(1) << 4; - epB[3] |= bit.read(1) << 3; - break; - - case 7: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(9) << 0; - epR[0] |= bit.read(1) << 10; - epG[1] |= bit.read(9) << 0; - epG[0] |= bit.read(1) << 10; - epB[1] |= bit.read(9) << 0; - epB[0] |= bit.read(1) << 10; - break; - - case 10: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(4) << 0; - epR[0] |= bit.read(1) << 10; - epB[2] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(4) << 0; - epG[0] |= bit.read(1) << 10; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(5) << 0; - epB[0] |= bit.read(1) << 10; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(4) << 0; - epB[3] |= bit.read(1) << 1; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(4) << 0; - epB[3] |= bit.read(1) << 4; - epB[3] |= bit.read(1) << 3; - break; - - case 11: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(8) << 0; - epR[0] |= bit.read(1) << 11; - epR[0] |= bit.read(1) << 10; - epG[1] |= bit.read(8) << 0; - epG[0] |= bit.read(1) << 11; - epG[0] |= bit.read(1) << 10; - epB[1] |= bit.read(8) << 0; - epB[0] |= bit.read(1) << 11; - epB[0] |= bit.read(1) << 10; - break; - - case 14: - epR[0] |= bit.read(9) << 0; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(9) << 0; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(9) << 0; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(5) << 0; - epG[3] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 3; - break; - - case 15: - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(4) << 0; - epR[0] |= bit.read(1) << 15; - epR[0] |= bit.read(1) << 14; - epR[0] |= bit.read(1) << 13; - epR[0] |= bit.read(1) << 12; - epR[0] |= bit.read(1) << 11; - epR[0] |= bit.read(1) << 10; - epG[1] |= bit.read(4) << 0; - epG[0] |= bit.read(1) << 15; - epG[0] |= bit.read(1) << 14; - epG[0] |= bit.read(1) << 13; - epG[0] |= bit.read(1) << 12; - epG[0] |= bit.read(1) << 11; - epG[0] |= bit.read(1) << 10; - epB[1] |= bit.read(4) << 0; - epB[0] |= bit.read(1) << 15; - epB[0] |= bit.read(1) << 14; - epB[0] |= bit.read(1) << 13; - epB[0] |= bit.read(1) << 12; - epB[0] |= bit.read(1) << 11; - epB[0] |= bit.read(1) << 10; - break; - - case 18: - epR[0] |= bit.read(8) << 0; - epG[3] |= bit.read(1) << 4; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(8) << 0; - epB[3] |= bit.read(1) << 2; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(8) << 0; - epB[3] |= bit.read(1) << 3; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(6) << 0; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(6) << 0; - epR[3] |= bit.read(6) << 0; - break; - - case 22: - epR[0] |= bit.read(8) << 0; - epB[3] |= bit.read(1) << 0; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(8) << 0; - epG[2] |= bit.read(1) << 5; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(8) << 0; - epG[3] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(5) << 0; - epG[3] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(6) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 3; - break; - - case 26: - epR[0] |= bit.read(8) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(8) << 0; - epB[2] |= bit.read(1) << 5; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(8) << 0; - epB[3] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(5) << 0; - epG[3] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(6) << 0; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 3; - break; - - case 30: - epR[0] |= bit.read(6) << 0; - epG[3] |= bit.read(1) << 4; - epB[3] |= bit.read(1) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(6) << 0; - epG[2] |= bit.read(1) << 5; - epB[2] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 2; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(6) << 0; - epG[3] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 3; - epB[3] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(6) << 0; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(6) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(6) << 0; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(6) << 0; - epR[3] |= bit.read(6) << 0; - break; - - default: - break; - } - } - else - { - switch (mode) - { - case 0: - epG[2] |= bit.read(1) << 4; - epB[2] |= bit.read(1) << 4; - epB[3] |= bit.read(1) << 4; - epR[0] |= bit.read(10) << 0; - epG[0] |= bit.read(10) << 0; - epB[0] |= bit.read(10) << 0; - epR[1] |= bit.read(5) << 0; - epG[3] |= bit.read(1) << 4; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 2; - epR[3] |= bit.read(5) << 0; - epB[3] |= bit.read(1) << 3; - break; - - case 1: - epG[2] |= bit.read(1) << 5; - epG[3] |= bit.read(1) << 4; - epG[3] |= bit.read(1) << 5; - epR[0] |= bit.read(7) << 0; - epB[3] |= bit.read(1) << 0; - epB[3] |= bit.read(1) << 1; - epB[2] |= bit.read(1) << 4; - epG[0] |= bit.read(7) << 0; - epB[2] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 2; - epG[2] |= bit.read(1) << 4; - epB[0] |= bit.read(7) << 0; - epB[3] |= bit.read(1) << 3; - epB[3] |= bit.read(1) << 5; - epB[3] |= bit.read(1) << 4; - epR[1] |= bit.read(6) << 0; - epG[2] |= bit.read(4) << 0; - epG[1] |= bit.read(6) << 0; - epG[3] |= bit.read(4) << 0; - epB[1] |= bit.read(6) << 0; - epB[2] |= bit.read(4) << 0; - epR[2] |= bit.read(6) << 0; - epR[3] |= bit.read(6) << 0; - break; - - default: - break; - } - } - - const Bc6hModeInfo mi = s_bc6hModeInfo[mode]; - - if (_signed) - { - epR[0] = sign_extend(epR[0], mi.endpointBits); - epG[0] = sign_extend(epG[0], mi.endpointBits); - epB[0] = sign_extend(epB[0], mi.endpointBits); - } - - const uint8_t numSubsets = !!mi.partitionBits + 1; - - for (uint8_t ii = 1, num = numSubsets * 2; ii < num; ++ii) - { - if (_signed - || mi.transformed) - { - epR[ii] = sign_extend(epR[ii], mi.deltaBits[0]); - epG[ii] = sign_extend(epG[ii], mi.deltaBits[1]); - epB[ii] = sign_extend(epB[ii], mi.deltaBits[2]); - } - - if (mi.transformed) - { - const uint16_t mask = (1 << mi.endpointBits) - 1; - - epR[ii] = (epR[ii] + epR[0]) & mask; - epG[ii] = (epG[ii] + epG[0]) & mask; - epB[ii] = (epB[ii] + epB[0]) & mask; - - if (_signed) - { - epR[ii] = sign_extend(epR[ii], mi.endpointBits); - epG[ii] = sign_extend(epG[ii], mi.endpointBits); - epB[ii] = sign_extend(epB[ii], mi.endpointBits); - } - } - } - - for (uint8_t ii = 0, num = numSubsets * 2; ii < num; ++ii) - { - epR[ii] = unquantize(epR[ii], _signed, mi.endpointBits); - epG[ii] = unquantize(epG[ii], _signed, mi.endpointBits); - epB[ii] = unquantize(epB[ii], _signed, mi.endpointBits); - } - - const uint8_t partitionSetIdx = uint8_t(mi.partitionBits ? bit.read(5) : 0); - const uint8_t indexBits = mi.partitionBits ? 3 : 4; - const uint8_t* factors = s_bptcFactors[indexBits - 2]; - - for (uint8_t yy = 0; yy < 4; ++yy) - { - for (uint8_t xx = 0; xx < 4; ++xx) - { - const uint8_t idx = yy * 4 + xx; - - uint8_t subsetIndex = 0; - uint8_t indexAnchor = 0; - - if (0 != mi.partitionBits) - { - subsetIndex = (s_bptcP2[partitionSetIdx] >> idx) & 1; - indexAnchor = subsetIndex ? s_bptcA2[partitionSetIdx] : 0; - } - - const uint8_t anchor = idx == indexAnchor; - const uint8_t num = indexBits - anchor; - const uint8_t index = (uint8_t)bit.read(num); - - const uint8_t fc = factors[index]; - const uint8_t fca = 64 - fc; - const uint8_t fcb = fc; - - subsetIndex *= 2; - uint16_t rr = finish_unquantize((epR[subsetIndex] * fca + epR[subsetIndex + 1] * fcb + 32) >> 6, _signed); - uint16_t gg = finish_unquantize((epG[subsetIndex] * fca + epG[subsetIndex + 1] * fcb + 32) >> 6, _signed); - uint16_t bb = finish_unquantize((epB[subsetIndex] * fca + epB[subsetIndex + 1] * fcb + 32) >> 6, _signed); - - _dst[idx] = color(half_to_u8(rr), half_to_u8(gg), half_to_u8(bb), 255); - } - } -} - -int decode_bc6(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) { - decode_bc6_block(data, buffer, false); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} - -static const uint32_t s_bptcP3[] = -{ // 76543210 0000 1111 2222 3333 4444 5555 6666 7777 - 0xaa685050, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 - 0x6a5a5040, // 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 - 0x5a5a4200, // 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 - 0x5450a0a8, // 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 - 0xa5a50000, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 - 0xa0a05050, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 - 0x5555a0a0, // 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 - 0x5a5a5050, // 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 - 0xaa550000, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 - 0xaa555500, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 - 0xaaaa5500, // 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 - 0x90909090, // 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 - 0x94949494, // 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 - 0xa4a4a4a4, // 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 - 0xa9a59450, // 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 - 0x2a0a4250, // 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 - 0xa5945040, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 - 0x0a425054, // 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 - 0xa5a5a500, // 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 - 0x55a0a0a0, // 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 - 0xa8a85454, // 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 - 0x6a6a4040, // 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 - 0xa4a45000, // 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 - 0x1a1a0500, // 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 - 0x0050a4a4, // 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 - 0xaaa59090, // 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 - 0x14696914, // 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 - 0x69691400, // 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 - 0xa08585a0, // 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 - 0xaa821414, // 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 - 0x50a4a450, // 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 - 0x6a5a0200, // 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 - 0xa9a58000, // 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 - 0x5090a0a8, // 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 - 0xa8a09050, // 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 - 0x24242424, // 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 - 0x00aa5500, // 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 - 0x24924924, // 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 - 0x24499224, // 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 - 0x50a50a50, // 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 - 0x500aa550, // 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 - 0xaaaa4444, // 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 - 0x66660000, // 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 - 0xa5a0a5a0, // 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 - 0x50a050a0, // 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 - 0x69286928, // 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 - 0x44aaaa44, // 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 - 0x66666600, // 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 - 0xaa444444, // 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 - 0x54a854a8, // 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 - 0x95809580, // 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 - 0x96969600, // 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 - 0xa85454a8, // 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 - 0x80959580, // 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 - 0xaa141414, // 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 - 0x96960000, // 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 - 0xaaaa1414, // 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 - 0xa05050a0, // 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 - 0xa0a5a5a0, // 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 - 0x96000000, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 - 0x40804080, // 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 - 0xa9a8a9a8, // 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 - 0xaaaaaa44, // 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 - 0x2a4a5254, // 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 -}; - -static const uint8_t s_bptcA3[2][64] = -{ - { - 3, 3, 15, 15, 8, 3, 15, 15, - 8, 8, 6, 6, 6, 5, 3, 3, - 3, 3, 8, 15, 3, 3, 6, 10, - 5, 8, 8, 6, 8, 5, 15, 15, - 8, 15, 3, 5, 6, 10, 8, 15, - 15, 3, 15, 5, 15, 15, 15, 15, - 3, 15, 5, 5, 5, 8, 5, 10, - 5, 10, 8, 13, 15, 12, 3, 3, - }, - { - 15, 8, 8, 3, 15, 15, 3, 8, - 15, 15, 15, 15, 15, 15, 15, 8, - 15, 8, 15, 3, 15, 8, 15, 8, - 3, 15, 6, 10, 15, 15, 10, 8, - 15, 3, 15, 10, 10, 8, 9, 10, - 6, 15, 8, 15, 3, 6, 6, 8, - 15, 3, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 3, 15, 15, 8, - }, -}; - -struct Bc7ModeInfo -{ - uint8_t numSubsets; - uint8_t partitionBits; - uint8_t rotationBits; - uint8_t indexSelectionBits; - uint8_t colorBits; - uint8_t alphaBits; - uint8_t endpointPBits; - uint8_t sharedPBits; - uint8_t indexBits[2]; -}; - -static const Bc7ModeInfo s_bp7ModeInfo[] = -{ // +---------------------------- num subsets - // | +------------------------- partition bits - // | | +---------------------- rotation bits - // | | | +------------------- index selection bits - // | | | | +---------------- color bits - // | | | | | +------------- alpha bits - // | | | | | | +---------- endpoint P-bits - // | | | | | | | +------- shared P-bits - // | | | | | | | | +-- 2x index bits - { 3, 4, 0, 0, 4, 0, 1, 0, { 3, 0 } }, // 0 - { 2, 6, 0, 0, 6, 0, 0, 1, { 3, 0 } }, // 1 - { 3, 6, 0, 0, 5, 0, 0, 0, { 2, 0 } }, // 2 - { 2, 6, 0, 0, 7, 0, 1, 0, { 2, 0 } }, // 3 - { 1, 0, 2, 1, 5, 6, 0, 0, { 2, 3 } }, // 4 - { 1, 0, 2, 0, 7, 8, 0, 0, { 2, 2 } }, // 5 - { 1, 0, 0, 0, 7, 7, 1, 0, { 4, 0 } }, // 6 - { 2, 6, 0, 0, 5, 5, 1, 0, { 2, 0 } }, // 7 -}; - -static uint8_t expand_quantized(uint8_t v, int bits) { - v = v << (8 - bits); - return v | (v >> bits); -} - -static void decode_bc7_block(const uint8_t* _src, uint32_t* _dst) -{ - BitReader bit(_src); - - uint8_t mode = 0; - for (; mode < 8 && 0 == bit.read(1); ++mode) - { - } - - if (mode == 8) - { - memset(_dst, 0, 16 * 4); - return; - } - - const Bc7ModeInfo& mi = s_bp7ModeInfo[mode]; - const uint8_t modePBits = 0 != mi.endpointPBits - ? mi.endpointPBits - : mi.sharedPBits - ; - - const uint8_t partitionSetIdx = uint8_t(bit.read(mi.partitionBits)); - const uint8_t rotationMode = uint8_t(bit.read(mi.rotationBits)); - const uint8_t indexSelectionMode = uint8_t(bit.read(mi.indexSelectionBits)); - - uint8_t epR[6]; - uint8_t epG[6]; - uint8_t epB[6]; - uint8_t epA[6]; - - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epR[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits); - epR[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits); - } - - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epG[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits); - epG[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits); - } - - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epB[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits); - epB[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits); - } - - if (mi.alphaBits) - { - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epA[ii * 2 + 0] = uint8_t(bit.read(mi.alphaBits) << modePBits); - epA[ii * 2 + 1] = uint8_t(bit.read(mi.alphaBits) << modePBits); - } - } - else - { - memset(epA, 0xff, 6); - } - - if (0 != modePBits) - { - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - const uint8_t pda = uint8_t(bit.read(modePBits)); - const uint8_t pdb = uint8_t(0 == mi.sharedPBits ? bit.read(modePBits) : pda); - - epR[ii * 2 + 0] |= pda; - epR[ii * 2 + 1] |= pdb; - epG[ii * 2 + 0] |= pda; - epG[ii * 2 + 1] |= pdb; - epB[ii * 2 + 0] |= pda; - epB[ii * 2 + 1] |= pdb; - epA[ii * 2 + 0] |= pda; - epA[ii * 2 + 1] |= pdb; - } - } - - const uint8_t colorBits = mi.colorBits + modePBits; - - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epR[ii * 2 + 0] = expand_quantized(epR[ii * 2 + 0], colorBits); - epR[ii * 2 + 1] = expand_quantized(epR[ii * 2 + 1], colorBits); - epG[ii * 2 + 0] = expand_quantized(epG[ii * 2 + 0], colorBits); - epG[ii * 2 + 1] = expand_quantized(epG[ii * 2 + 1], colorBits); - epB[ii * 2 + 0] = expand_quantized(epB[ii * 2 + 0], colorBits); - epB[ii * 2 + 1] = expand_quantized(epB[ii * 2 + 1], colorBits); - } - - if (mi.alphaBits) - { - const uint8_t alphaBits = mi.alphaBits + modePBits; - - for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) - { - epA[ii * 2 + 0] = expand_quantized(epA[ii * 2 + 0], alphaBits); - epA[ii * 2 + 1] = expand_quantized(epA[ii * 2 + 1], alphaBits); - } - } - - const bool hasIndexBits1 = 0 != mi.indexBits[1]; - - const uint8_t* factors[] = - { - s_bptcFactors[mi.indexBits[0] - 2], - hasIndexBits1 ? s_bptcFactors[mi.indexBits[1] - 2] : factors[0], - }; - - uint16_t offset[2] = - { - 0, - uint16_t(mi.numSubsets * (16 * mi.indexBits[0] - 1)), - }; - - for (uint8_t yy = 0; yy < 4; ++yy) - { - for (uint8_t xx = 0; xx < 4; ++xx) - { - const uint8_t idx = yy * 4 + xx; - - uint8_t subsetIndex = 0; - uint8_t indexAnchor = 0; - switch (mi.numSubsets) - { - case 2: - subsetIndex = (s_bptcP2[partitionSetIdx] >> idx) & 1; - indexAnchor = 0 != subsetIndex ? s_bptcA2[partitionSetIdx] : 0; - break; - - case 3: - subsetIndex = (s_bptcP3[partitionSetIdx] >> (2 * idx)) & 3; - indexAnchor = 0 != subsetIndex ? s_bptcA3[subsetIndex - 1][partitionSetIdx] : 0; - break; - - default: - break; - } - - const uint8_t anchor = idx == indexAnchor; - const uint8_t num[2] = - { - uint8_t(mi.indexBits[0] - anchor), - uint8_t(hasIndexBits1 ? mi.indexBits[1] - anchor : 0), - }; - - const uint8_t index[2] = - { - (uint8_t)bit.peek(offset[0], num[0]), - hasIndexBits1 ? (uint8_t)bit.peek(offset[1], num[1]) : index[0], - }; - - offset[0] += num[0]; - offset[1] += num[1]; - - const uint8_t fc = factors[indexSelectionMode][index[indexSelectionMode]]; - const uint8_t fa = factors[!indexSelectionMode][index[!indexSelectionMode]]; - - const uint8_t fca = 64 - fc; - const uint8_t fcb = fc; - const uint8_t faa = 64 - fa; - const uint8_t fab = fa; - - subsetIndex *= 2; - uint8_t rr = uint8_t(uint16_t(epR[subsetIndex] * fca + epR[subsetIndex + 1] * fcb + 32) >> 6); - uint8_t gg = uint8_t(uint16_t(epG[subsetIndex] * fca + epG[subsetIndex + 1] * fcb + 32) >> 6); - uint8_t bb = uint8_t(uint16_t(epB[subsetIndex] * fca + epB[subsetIndex + 1] * fcb + 32) >> 6); - uint8_t aa = uint8_t(uint16_t(epA[subsetIndex] * faa + epA[subsetIndex + 1] * fab + 32) >> 6); - - switch (rotationMode) - { - case 1: std::swap(aa, rr); break; - case 2: std::swap(aa, gg); break; - case 3: std::swap(aa, bb); break; - default: break; - }; - - _dst[idx] = color(rr, gg, bb, aa); - } - } -} - -int decode_bc7(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) { - uint32_t m_block_width = 4; - uint32_t m_block_height = 4; - uint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width; - uint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height; - uint32_t buffer[16]; - for (uint32_t by = 0; by < m_blocks_y; by++) { - for (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) { - decode_bc7_block(data, buffer); - copy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image); - } - } - return 1; -} \ No newline at end of file diff --git a/Texture2DDecoderNative/bcn.h b/Texture2DDecoderNative/bcn.h deleted file mode 100644 index bfcdfde..0000000 --- a/Texture2DDecoderNative/bcn.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include - -struct color_bgra -{ - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t a; -}; - -const color_bgra g_black_color{ 0, 0, 0, 255 }; - -int decode_bc1(const uint8_t* data, const long w, const long h, uint32_t* image); -void decode_bc3_alpha(const uint8_t* data, uint32_t* outbuf, int channel); -int decode_bc3(const uint8_t* data, const long w, const long h, uint32_t* image); -int decode_bc4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); -int decode_bc5(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); -int decode_bc6(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); -int decode_bc7(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image); \ No newline at end of file diff --git a/Texture2DDecoderNative/bool32_t.h b/Texture2DDecoderNative/bool32_t.h deleted file mode 100644 index 2b2d6b2..0000000 --- a/Texture2DDecoderNative/bool32_t.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -typedef uint32_t bool32_t; diff --git a/Texture2DDecoderNative/color.h b/Texture2DDecoderNative/color.h deleted file mode 100644 index 685f87e..0000000 --- a/Texture2DDecoderNative/color.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef COLOR_H -#define COLOR_H - -#include -#include -#include "endianness.h" - -#ifdef __LITTLE_ENDIAN__ -static const uint_fast32_t TRANSPARENT_MASK = 0x00ffffff; -#else -static const uint_fast32_t TRANSPARENT_MASK = 0xffffff00; -#endif - -static inline uint_fast32_t color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { -#ifdef __LITTLE_ENDIAN__ - return b | g << 8 | r << 16 | a << 24; -#else - return a | r << 8 | g << 16 | b << 24; -#endif -} - -static inline uint_fast32_t alpha_mask(uint8_t a) { -#ifdef __LITTLE_ENDIAN__ - return TRANSPARENT_MASK | a << 24; -#else - return TRANSPARENT_MASK | a; -#endif -} - -static inline void rgb565_le(const uint16_t d, uint8_t *r, uint8_t *g, uint8_t *b) { -#ifdef __LITTLE_ENDIAN__ - *r = (d >> 8 & 0xf8) | (d >> 13); - *g = (d >> 3 & 0xfc) | (d >> 9 & 3); - *b = (d << 3) | (d >> 2 & 7); -#else - *r = (d & 0xf8) | (d >> 5 & 7); - *g = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3); - *b = (d >> 5 & 0xf8) | (d >> 10 & 0x7); -#endif -} - -static inline void rgb565_be(const uint16_t d, uint8_t *r, uint8_t *g, uint8_t *b) { -#ifdef __BIG_ENDIAN__ - *r = (d >> 8 & 0xf8) | (d >> 13); - *g = (d >> 3 & 0xfc) | (d >> 9 & 3); - *b = (d << 3) | (d >> 2 & 7); -#else - *r = (d & 0xf8) | (d >> 5 & 7); - *g = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3); - *b = (d >> 5 & 0xf8) | (d >> 10 & 0x7); -#endif -} - -static inline void rgb565_lep(const uint16_t d, uint8_t *c) { -#ifdef __LITTLE_ENDIAN__ - *(c++) = (d >> 8 & 0xf8) | (d >> 13); - *(c++) = (d >> 3 & 0xfc) | (d >> 9 & 3); - *(c++) = (d << 3) | (d >> 2 & 7); -#else - *(c++) = (d & 0xf8) | (d >> 5 & 7); - *(c++) = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3); - *(c++) = (d >> 5 & 0xf8) | (d >> 10 & 0x7); -#endif -} - -static inline void rgb565_bep(const uint16_t d, uint8_t *c) { -#ifdef __BIG_ENDIAN__ - *(c++) = (d >> 8 & 0xf8) | (d >> 13); - *(c++) = (d >> 3 & 0xfc) | (d >> 9 & 3); - *(c++) = (d << 3) | (d >> 2 & 7); -#else - *(c++) = (d & 0xf8) | (d >> 5 & 7); - *(c++) = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3); - *(c++) = (d >> 5 & 0xf8) | (d >> 10 & 0x7); -#endif -} - -static inline void copy_block_buffer(const long bx, const long by, const long w, const long h, const long bw, - const long bh, const uint32_t *buffer, uint32_t *image) { - long x = bw * bx; - long xl = (bw * (bx + 1) > w ? w - bw * bx : bw) * 4; - const uint32_t *buffer_end = buffer + bw * bh; - for (long y = by * bh; buffer < buffer_end && y < h; buffer += bw, y++) - memcpy(image + y * w + x, buffer, xl); -} - -#endif /* end of include guard: COLOR_H */ diff --git a/Texture2DDecoderNative/cpp.hint b/Texture2DDecoderNative/cpp.hint deleted file mode 100644 index 63084fd..0000000 --- a/Texture2DDecoderNative/cpp.hint +++ /dev/null @@ -1 +0,0 @@ -#define T2D_API(ret_type) diff --git a/Texture2DDecoderNative/crunch.cpp b/Texture2DDecoderNative/crunch.cpp deleted file mode 100644 index 714b852..0000000 --- a/Texture2DDecoderNative/crunch.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "crunch.h" -#include -#include -#include "crunch/crn_decomp.h" - -bool crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size) { - crnd::crn_texture_info tex_info; - if (!crnd::crnd_get_texture_info(data, data_size, &tex_info)) - { - return false; - } - - crnd::crnd_unpack_context pContext = crnd::crnd_unpack_begin(data, data_size); - if (!pContext) - { - return false; - } - - const crn_uint32 width = std::max(1U, tex_info.m_width >> level_index); - const crn_uint32 height = std::max(1U, tex_info.m_height >> level_index); - const crn_uint32 blocks_x = std::max(1U, (width + 3) >> 2); - const crn_uint32 blocks_y = std::max(1U, (height + 3) >> 2); - const crn_uint32 row_pitch = blocks_x * crnd::crnd_get_bytes_per_dxt_block(tex_info.m_format); - const crn_uint32 total_face_size = row_pitch * blocks_y; - *ret = new uint8_t[total_face_size]; - *ret_size = total_face_size; - if (!crnd::crnd_unpack_level(pContext, ret, total_face_size, row_pitch, level_index)) - { - crnd::crnd_unpack_end(pContext); - return false; - } - crnd::crnd_unpack_end(pContext); - return true; -} \ No newline at end of file diff --git a/Texture2DDecoderNative/crunch.h b/Texture2DDecoderNative/crunch.h deleted file mode 100644 index 21ac55c..0000000 --- a/Texture2DDecoderNative/crunch.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -bool crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size); \ No newline at end of file diff --git a/Texture2DDecoderNative/crunch/crn_decomp.h b/Texture2DDecoderNative/crunch/crn_decomp.h deleted file mode 100644 index 53311cd..0000000 --- a/Texture2DDecoderNative/crunch/crn_decomp.h +++ /dev/null @@ -1,4843 +0,0 @@ -// File: crn_decomp.h - Fast CRN->DXTc texture transcoder header file library -// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved. -// See Copyright Notice and license at the end of this file. -// -// This single header file contains *all* of the code necessary to unpack .CRN files to raw DXTn bits. -// It does NOT depend on the crn compression library. -// -// Note: This is a single file, stand-alone C++ library which is controlled by the use of two macros: -// If CRND_INCLUDE_CRND_H is NOT defined, the header is included. -// If CRND_HEADER_FILE_ONLY is NOT defined, the implementation is included. -// -// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing -#ifndef CRND_INCLUDE_CRND_H -#define CRND_INCLUDE_CRND_H - -// Include crnlib.h (only to bring in some basic CRN-related types). -#include "crnlib.h" - -#define CRND_LIB_VERSION 104 -#define CRND_VERSION_STRING "01.04" - -#ifdef _DEBUG -#define CRND_BUILD_DEBUG -#else -#define CRND_BUILD_RELEASE -#endif - -// CRN decompression API -namespace crnd -{ - typedef unsigned char uint8; - typedef signed char int8; - typedef unsigned short uint16; - typedef signed short int16; - typedef unsigned int uint32; - typedef uint32 uint32; - typedef unsigned int uint; - typedef signed int int32; - #ifdef __GNUC__ - typedef unsigned long long uint64; - typedef long long int64; - #else - typedef unsigned __int64 uint64; - typedef signed __int64 int64; - #endif - - // The crnd library assumes all allocation blocks have at least CRND_MIN_ALLOC_ALIGNMENT alignment. - const uint32 CRND_MIN_ALLOC_ALIGNMENT = sizeof(uint32) * 2U; - - // realloc callback: - // Used to allocate, resize, or free memory blocks. - // If p is NULL, the realloc function attempts to allocate a block of at least size bytes. Returns NULL on out of memory. - // *pActual_size must be set to the actual size of the allocated block, which must be greater than or equal to the requested size. - // If p is not NULL, and size is 0, the realloc function frees the specified block, and always returns NULL. *pActual_size should be set to 0. - // If p is not NULL, and size is non-zero, the realloc function attempts to resize the specified block: - // If movable is false, the realloc function attempts to shrink or expand the block in-place. NULL is returned if the block cannot be resized in place, or if the - // underlying heap implementation doesn't support in-place resizing. Otherwise, the pointer to the original block is returned. - // If movable is true, it is permissible to move the block's contents if it cannot be resized in place. NULL is returned if the block cannot be resized in place, and there - // is not enough memory to relocate the block. - // In all cases, *pActual_size must be set to the actual size of the allocated block, whether it was successfully resized or not. - typedef void* (*crnd_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data); - - // msize callback: Returns the size of the memory block in bytes, or 0 if the pointer or block is invalid. - typedef size_t (*crnd_msize_func)(void* p, void* pUser_data); - - // crnd_set_memory_callbacks() - Use to override the crnd library's memory allocation functions. - // If any input parameters are NULL, the memory callback functions are reset to the default functions. - // The default functions call malloc(), free(), _msize(), _expand(), etc. - void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data); - - struct crn_file_info - { - inline crn_file_info() : m_struct_size(sizeof(crn_file_info)) { } - - uint32 m_struct_size; - uint32 m_actual_data_size; - uint32 m_header_size; - uint32 m_total_palette_size; - uint32 m_tables_size; - uint32 m_levels; - uint32 m_level_compressed_size[cCRNMaxLevels]; - uint32 m_color_endpoint_palette_entries; - uint32 m_color_selector_palette_entries; - uint32 m_alpha_endpoint_palette_entries; - uint32 m_alpha_selector_palette_entries; - }; - - struct crn_texture_info - { - inline crn_texture_info() : m_struct_size(sizeof(crn_texture_info)) { } - - uint32 m_struct_size; - uint32 m_width; - uint32 m_height; - uint32 m_levels; - uint32 m_faces; - uint32 m_bytes_per_block; - uint32 m_userdata0; - uint32 m_userdata1; - crn_format m_format; - }; - - struct crn_level_info - { - inline crn_level_info() : m_struct_size(sizeof(crn_level_info)) { } - - uint32 m_struct_size; - uint32 m_width; - uint32 m_height; - uint32 m_faces; - uint32 m_blocks_x; - uint32 m_blocks_y; - uint32 m_bytes_per_block; - crn_format m_format; - }; - - // Returns the FOURCC format code corresponding to the specified CRN format. - uint32 crnd_crn_format_to_fourcc(crn_format fmt); - - // Returns the fundamental GPU format given a potentially swizzled DXT5 crn_format. - crn_format crnd_get_fundamental_dxt_format(crn_format fmt); - - // Returns the size of the crn_format in bits/texel (either 4 or 8). - uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt); - - // Returns the number of bytes per DXTn block (8 or 16). - uint32 crnd_get_bytes_per_dxt_block(crn_format fmt); - - // Validates the entire file by checking the header and data CRC's. - // This is not something you want to be doing much! - // The crn_file_info.m_struct_size field must be set before calling this function. - bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info); - - // Retrieves texture information from the CRN file. - // The crn_texture_info.m_struct_size field must be set before calling this function. - bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pTexture_info); - - // Retrieves mipmap level specific information from the CRN file. - // The crn_level_info.m_struct_size field must be set before calling this function. - bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info); - - // Transcode/unpack context handle. - typedef void* crnd_unpack_context; - - // crnd_unpack_begin() - Decompresses the texture's decoder tables and endpoint/selector palettes. - // Once you call this function, you may call crnd_unpack_level() to unpack one or more mip levels. - // Don't call this once per mip level (unless you absolutely must)! - // This function allocates enough memory to hold: Huffman decompression tables, and the endpoint/selector palettes (color and/or alpha). - // Worst case allocation is approx. 200k, assuming all palettes contain 8192 entries. - // pData must point to a buffer holding all of the compressed .CRN file data. - // This buffer must be stable until crnd_unpack_end() is called. - // Returns NULL if out of memory, or if any of the input parameters are invalid. - crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size); - - // Returns a pointer to the compressed .CRN data associated with a crnd_unpack_context. - // Returns false if any of the input parameters are invalid. - bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size); - - // crnd_unpack_level() - Transcodes the specified mipmap level to a destination buffer in cached or write combined memory. - // pContext - Context created by a call to crnd_unpack_begin(). - // ppDst - A pointer to an array of 1 or 6 destination buffer pointers. Cubemaps require an array of 6 pointers, 2D textures require an array of 1 pointer. - // dst_size_in_bytes - Optional size of each destination buffer. Only used for debugging - OK to set to UINT32_MAX. - // row_pitch_in_bytes - The pitch in bytes from one row of DXT blocks to the next. Must be a multiple of 4. - // level_index - mipmap level index, where 0 is the largest/first level. - // Returns false if any of the input parameters, or the compressed stream, are invalid. - // This function does not allocate any memory. - bool crnd_unpack_level( - crnd_unpack_context pContext, - void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index); - - // crnd_unpack_level_segmented() - Unpacks the specified mipmap level from a "segmented" CRN file. - // See the crnd_create_segmented_file() API below. - // Segmented files allow the user to control where the compressed mipmap data is stored. - bool crnd_unpack_level_segmented( - crnd_unpack_context pContext, - const void* pSrc, uint32 src_size_in_bytes, - void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index); - - // crnd_unpack_end() - Frees the decompress tables and unpacked palettes associated with the specified unpack context. - // Returns false if the context is NULL, or if it points to an invalid context. - // This function frees all memory associated with the context. - bool crnd_unpack_end(crnd_unpack_context pContext); - - // The following API's allow the user to create "segmented" CRN files. A segmented file contains multiple pieces: - // - Base data: Header + compression tables - // - Level data: Individual mipmap levels - // This allows mipmap levels from multiple CRN files to be tightly packed together into single files. - - // Returns a pointer to the level's compressed data, and optionally returns the level's compressed data size if pSize is not NULL. - const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize); - - // Returns the compressed size of the texture's header and compression tables (but no levels). - uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size); - - // Creates a "segmented" CRN texture from a normal CRN texture. The new texture will be created at pBase_data, and will be crnd_get_base_data_size() bytes long. - // base_data_size must be >= crnd_get_base_data_size(). - // The base data will contain the CRN header and compression tables, but no mipmap data. - bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size); - -} // namespace crnd - -// Low-level CRN file header cracking. -namespace crnd -{ - template - struct crn_packed_uint - { - inline crn_packed_uint() { } - - inline crn_packed_uint(unsigned int val) { *this = val; } - - inline crn_packed_uint(const crn_packed_uint& other) { *this = other; } - - inline crn_packed_uint& operator= (const crn_packed_uint& rhs) - { - if (this != &rhs) - memcpy(m_buf, rhs.m_buf, sizeof(m_buf)); - return *this; - } - - inline crn_packed_uint& operator= (unsigned int val) - { - //CRND_ASSERT((N == 4U) || (val < (1U << (N * 8U)))); - - val <<= (8U * (4U - N)); - - for (unsigned int i = 0; i < N; i++) - { - m_buf[i] = static_cast(val >> 24U); - val <<= 8U; - } - - return *this; - } - - inline operator unsigned int() const - { - switch (N) - { - case 1: return m_buf[0]; - case 2: return (m_buf[0] << 8U) | m_buf[1]; - case 3: return (m_buf[0] << 16U) | (m_buf[1] << 8U) | (m_buf[2]); - default: return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]); - } - } - - unsigned char m_buf[N]; - }; - -#pragma pack(push) -#pragma pack(1) - struct crn_palette - { - crn_packed_uint<3> m_ofs; - crn_packed_uint<3> m_size; - crn_packed_uint<2> m_num; - }; - - enum crn_header_flags - { - // If set, the compressed mipmap level data is not located after the file's base data - it will be separately managed by the user instead. - cCRNHeaderFlagSegmented = 1 - }; - - struct crn_header - { - enum { cCRNSigValue = ('H' << 8) | 'x' }; - - crn_packed_uint<2> m_sig; - crn_packed_uint<2> m_header_size; - crn_packed_uint<2> m_header_crc16; - - crn_packed_uint<4> m_data_size; - crn_packed_uint<2> m_data_crc16; - - crn_packed_uint<2> m_width; - crn_packed_uint<2> m_height; - - crn_packed_uint<1> m_levels; - crn_packed_uint<1> m_faces; - - crn_packed_uint<1> m_format; - crn_packed_uint<2> m_flags; - - crn_packed_uint<4> m_reserved; - crn_packed_uint<4> m_userdata0; - crn_packed_uint<4> m_userdata1; - - crn_palette m_color_endpoints; - crn_palette m_color_selectors; - - crn_palette m_alpha_endpoints; - crn_palette m_alpha_selectors; - - crn_packed_uint<2> m_tables_size; - crn_packed_uint<3> m_tables_ofs; - - // m_level_ofs[] is actually an array of offsets: m_level_ofs[m_levels] - crn_packed_uint<4> m_level_ofs[1]; - }; - - const unsigned int cCRNHeaderMinSize = 62U; - -#pragma pack(pop) - -} // namespace crnd - -#endif // CRND_INCLUDE_CRND_H - -// Internal library source follows this line. - -#ifndef CRND_HEADER_FILE_ONLY - -#include -#include -#ifdef _WIN32 -#include -#else -#include -#endif -#include -#include // needed for placement new, _msize, _expand - -#define CRND_RESTRICT __restrict - -#ifdef _MSC_VER -#include -#pragma intrinsic(_WriteBarrier) -#pragma intrinsic(_ReadWriteBarrier) -#define CRND_WRITE_BARRIER _WriteBarrier(); -#define CRND_FULL_BARRIER _ReadWriteBarrier(); -#else -#define CRND_WRITE_BARRIER -#define CRND_FULL_BARRIER -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4127) // warning C4127: conditional expression is constant -#endif - -#ifdef CRND_DEVEL -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x500 -#endif -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef -#define NOMINMAX -#endif -#include "windows.h" // only for IsDebuggerPresent(), DebugBreak(), and OutputDebugStringA() -#endif - -// File: crnd_types.h -namespace crnd -{ - const crn_uint8 cUINT8_MIN = 0; - const crn_uint8 cUINT8_MAX = 0xFFU; - const uint16 cUINT16_MIN = 0; - const uint16 cUINT16_MAX = 0xFFFFU; - const uint32 cUINT32_MIN = 0; - const uint32 cUINT32_MAX = 0xFFFFFFFFU; - - const int8 cINT8_MIN = -128; - const int8 cINT8_MAX = 127; - const int16 cINT16_MIN = -32768; - const int16 cINT16_MAX = 32767; - const int32 cINT32_MIN = (-2147483647 - 1); - const int32 cINT32_MAX = 2147483647; - - enum eClear { cClear }; - - const uint32 cIntBits = 32U; - -#ifdef _WIN64 - typedef uint64 ptr_bits; -#else - #ifdef __x86_64__ - typedef uint64 ptr_bits; - #else - typedef uint32 ptr_bits; - #endif -#endif - - template struct int_traits { enum { cMin = crnd::cINT32_MIN, cMax = crnd::cINT32_MAX, cSigned = true }; }; - - template<> struct int_traits { enum { cMin = crnd::cINT8_MIN, cMax = crnd::cINT8_MAX, cSigned = true }; }; - template<> struct int_traits { enum { cMin = crnd::cINT16_MIN, cMax = crnd::cINT16_MAX, cSigned = true }; }; - template<> struct int_traits { enum { cMin = crnd::cINT32_MIN, cMax = crnd::cINT32_MAX, cSigned = true }; }; - - template<> struct int_traits { enum { cMin = 0, cMax = crnd::cUINT8_MAX, cSigned = false }; }; - template<> struct int_traits { enum { cMin = 0, cMax = crnd::cUINT16_MAX, cSigned = false }; }; - template<> struct int_traits { enum { cMin = 0, cMax = crnd::cUINT32_MAX, cSigned = false }; }; - - struct empty_type { }; - -} // namespace crnd - -// File: crnd_platform.h -namespace crnd -{ -#ifdef _XBOX - const bool c_crnd_little_endian_platform = false; - const bool c_crnd_big_endian_platform = true; -#define CRND_BIG_ENDIAN_PLATFORM 1 -#else - const bool c_crnd_little_endian_platform = true; - const bool c_crnd_big_endian_platform = false; -#endif - - bool crnd_is_debugger_present(); - void crnd_debug_break(); - void crnd_output_debug_string(const char* p); - - // actually in crnd_assert.cpp - void crnd_assert(const char* pExp, const char* pFile, unsigned line); - void crnd_fail(const char* pExp, const char* pFile, unsigned line); - -} // namespace crnd - -// File: crnd_assert.h -namespace crnd -{ - void crnd_assert(const char* pExp, const char* pFile, unsigned line); - -#ifdef NDEBUG -#define CRND_ASSERT(x) ((void)0) -#undef CRND_ASSERTS_ENABLED -#else -#define CRND_ASSERT(_exp) (void)( (!!(_exp)) || (crnd::crnd_assert(#_exp, __FILE__, __LINE__), 0) ) -#define CRND_ASSERTS_ENABLED -#endif - - void crnd_trace(const char* pFmt, va_list args); - void crnd_trace(const char* pFmt, ...); - -} // namespace crnd - -// File: crnd_helpers.h -namespace crnd -{ - namespace helpers - { - template struct rel_ops - { - friend bool operator!= (const T& x, const T& y) { return (!(x == y)); } - friend bool operator> (const T& x, const T& y) { return (y < x); } - friend bool operator<= (const T& x, const T& y) { return (!(y < x)); } - friend bool operator>= (const T& x, const T& y) { return (!(x < y)); } - }; - - template - inline T* construct(T* p) - { - return new (static_cast(p)) T; - } - - template - inline T* construct(T* p, const U& init) - { - return new (static_cast(p)) T(init); - } - - template - void construct_array(T* p, uint32 n) - { - T* q = p + n; - for ( ; p != q; ++p) - new (static_cast(p)) T; - } - - template - void construct_array(T* p, uint32 n, const U& init) - { - T* q = p + n; - for ( ; p != q; ++p) - new (static_cast(p)) T(init); - } - - template - inline void destruct(T* p) - { - p; - p->~T(); - } - - template inline void destruct_array(T* p, uint32 n) - { - T* q = p + n; - for ( ; p != q; ++p) - p->~T(); - } - - } // namespace helpers - -} // namespace crnd - -// File: crnd_traits.h -namespace crnd -{ - template - struct scalar_type - { - enum { cFlag = false }; - static inline void construct(T* p) { helpers::construct(p); } - static inline void construct(T* p, const T& init) { helpers::construct(p, init); } - static inline void construct_array(T* p, uint32 n) { helpers::construct_array(p, n); } - static inline void destruct(T* p) { helpers::destruct(p); } - static inline void destruct_array(T* p, uint32 n) { helpers::destruct_array(p, n); } - }; - - template struct scalar_type - { - enum { cFlag = true }; - static inline void construct(T** p) { memset(p, 0, sizeof(T*)); } - static inline void construct(T** p, T* init) { *p = init; } - static inline void construct_array(T** p, uint32 n) { memset(p, 0, sizeof(T*) * n); } - static inline void destruct(T** p) { p; } - static inline void destruct_array(T** p, uint32 n) { p, n; } - }; - -#define CRND_DEFINE_BUILT_IN_TYPE(X) \ - template<> struct scalar_type { \ - enum { cFlag = true }; \ - static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \ - static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \ - static inline void construct_array(X* p, uint32 n) { memset(p, 0, sizeof(X) * n); } \ - static inline void destruct(X* p) { p; } \ - static inline void destruct_array(X* p, uint32 n) { p, n; } }; - - CRND_DEFINE_BUILT_IN_TYPE(bool) - CRND_DEFINE_BUILT_IN_TYPE(char) - CRND_DEFINE_BUILT_IN_TYPE(unsigned char) - CRND_DEFINE_BUILT_IN_TYPE(short) - CRND_DEFINE_BUILT_IN_TYPE(unsigned short) - CRND_DEFINE_BUILT_IN_TYPE(int) - CRND_DEFINE_BUILT_IN_TYPE(unsigned int) - CRND_DEFINE_BUILT_IN_TYPE(long) - CRND_DEFINE_BUILT_IN_TYPE(unsigned long) - CRND_DEFINE_BUILT_IN_TYPE(int64) - CRND_DEFINE_BUILT_IN_TYPE(uint64) - CRND_DEFINE_BUILT_IN_TYPE(float) - CRND_DEFINE_BUILT_IN_TYPE(double) - CRND_DEFINE_BUILT_IN_TYPE(long double) - -#undef CRND_DEFINE_BUILT_IN_TYPE - - // See: http://erdani.org/publications/cuj-2004-06.pdf - - template - struct bitwise_movable { enum { cFlag = false }; }; - - // Defines type Q as bitwise movable. -#define CRND_DEFINE_BITWISE_MOVABLE(Q) template<> struct bitwise_movable { enum { cFlag = true }; }; - - // From yasli_traits.h: - // Credit goes to Boost; - // also found in the C++ Templates book by Vandevoorde and Josuttis - - typedef char (&yes_t)[1]; - typedef char (&no_t)[2]; - - template yes_t class_test(int U::*); - template no_t class_test(...); - - template struct is_class - { - enum { value = (sizeof(class_test(0)) == sizeof(yes_t)) }; - }; - - template struct is_pointer - { - enum { value = false }; - }; - - template struct is_pointer - { - enum { value = true }; - }; - -#define CRND_IS_POD(T) __is_pod(T) - -} // namespace crnd - -// File: crnd_mem.h -namespace crnd -{ - void* crnd_malloc(size_t size, size_t* pActual_size = NULL); - void* crnd_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true); - void crnd_free(void* p); - size_t crnd_msize(void* p); - - template - inline T* crnd_new() - { - T* p = static_cast(crnd_malloc(sizeof(T))); - if (!p) - return NULL; - - return helpers::construct(p); - } - - template - inline T* crnd_new(const T& init) - { - T* p = static_cast(crnd_malloc(sizeof(T))); - if (!p) - return NULL; - - return helpers::construct(p, init); - } - - template - inline T* crnd_new_array(uint32 num) - { - if (!num) num = 1; - - uint8* q = static_cast(crnd_malloc(CRND_MIN_ALLOC_ALIGNMENT + sizeof(T) * num)); - if (!q) - return NULL; - - T* p = reinterpret_cast(q + CRND_MIN_ALLOC_ALIGNMENT); - - reinterpret_cast(p)[-1] = num; - reinterpret_cast(p)[-2] = ~num; - - helpers::construct_array(p, num); - return p; - } - - template - inline void crnd_delete(T* p) - { - if (p) - { - helpers::destruct(p); - crnd_free(p); - } - } - - template - inline void crnd_delete_array(T* p) - { - if (p) - { - const uint32 num = reinterpret_cast(p)[-1]; - const uint32 num_check = reinterpret_cast(p)[-2]; - num_check; - CRND_ASSERT(num && (num == ~num_check)); - - helpers::destruct_array(p, num); - - crnd_free(reinterpret_cast(p) - CRND_MIN_ALLOC_ALIGNMENT); - } - } - -} // namespace crnd - -// File: crnd_math.h -namespace crnd -{ - namespace math - { - const float cNearlyInfinite = 1.0e+37f; - - const float cDegToRad = 0.01745329252f; - const float cRadToDeg = 57.29577951f; - - extern uint32 g_bitmasks[32]; - - // Yes I know these should probably be pass by ref, not val: - // http://www.stepanovpapers.com/notes.pdf - // Just don't use them on non-simple (non built-in) types! - template inline T minimum(T a, T b) - { - return (a < b) ? a : b; - } - - template inline T minimum(T a, T b, T c) - { - return minimum(minimum(a, b), c); - } - - template inline T maximum(T a, T b) - { - return (a > b) ? a : b; - } - - template inline T maximum(T a, T b, T c) - { - return maximum(maximum(a, b), c); - } - - template inline T clamp(T value, T low, T high) - { - return (value < low) ? low : ((value > high) ? high : value); - } - - template inline T square(T value) - { - return value * value; - } - - inline bool is_power_of_2(uint32 x) - { - return x && ((x & (x - 1U)) == 0U); - } - - // From "Hackers Delight" - inline int next_pow2(uint32 val) - { - val--; - val |= val >> 16; - val |= val >> 8; - val |= val >> 4; - val |= val >> 2; - val |= val >> 1; - return val + 1; - } - - // Returns the total number of bits needed to encode v. - inline uint32 total_bits(uint32 v) - { - uint32 l = 0; - while (v > 0U) - { - v >>= 1; - l++; - } - return l; - } - - inline uint floor_log2i(uint v) - { - uint l = 0; - while (v > 1U) - { - v >>= 1; - l++; - } - return l; - } - - inline uint ceil_log2i(uint v) - { - uint l = floor_log2i(v); - if ((l != cIntBits) && (v > (1U << l))) - l++; - return l; - } - } -} - -// File: crnd_utils.h -namespace crnd -{ - namespace utils - { - template inline void zero_object(T& obj) - { - memset(&obj, 0, sizeof(obj)); - } - - template inline void zero_this(T* pObj) - { - memset(pObj, 0, sizeof(*pObj)); - } - - template - inline void swap(T& left, T& right) - { - T temp(left); - left = right; - right = temp; - } - - inline void invert_buf(void* pBuf, uint32 size) - { - uint8* p = static_cast(pBuf); - - const uint32 half_size = size >> 1; - for (uint32 i = 0; i < half_size; i++) - swap(p[i], p[size - 1U - i]); - } - - static inline uint16 swap16(uint16 x) { return static_cast((x << 8) | (x >> 8)); } - static inline uint32 swap32(uint32 x) { return ((x << 24) | ((x << 8) & 0x00FF0000) | (( x >> 8) & 0x0000FF00) | (x >> 24)); } - - uint32 compute_max_mips(uint32 width, uint32 height); - - } // namespace utils - -} // namespace crnd - -// File: crnd_vector.h -namespace crnd -{ - struct elemental_vector - { - void* m_p; - uint32 m_size; - uint32 m_capacity; - - typedef void (*object_mover)(void* pDst, void* pSrc, uint32 num); - - bool increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pRelocate); - }; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) // warning C4127: conditional expression is constant -#endif - - template - class vector : public helpers::rel_ops< vector > - { - public: - typedef T* iterator; - typedef const T* const_iterator; - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - - inline vector() : - m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) - { - } - - inline vector(const vector& other) : - m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) - { - *this = other; - } - - inline vector(uint32 size) : - m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) - { - resize(size); - } - - inline ~vector() - { - clear(); - } - - // I don't like this. Not at all. But exceptions, or just failing suck worse. - inline bool get_alloc_failed() const { return m_alloc_failed; } - inline void clear_alloc_failed() { m_alloc_failed = false; } - - inline bool assign(const vector& other) - { - if (this == &other) - return true; - - if (m_capacity == other.m_size) - resize(0); - else - { - clear(); - - if (!increase_capacity(other.m_size, false)) - return false; - } - - if (scalar_type::cFlag) - memcpy(m_p, other.m_p, other.m_size * sizeof(T)); - else - { - T* pDst = m_p; - const T* pSrc = other.m_p; - for (uint32 i = other.m_size; i > 0; i--) - helpers::construct(pDst++, *pSrc++); - } - - m_size = other.m_size; - - return true; - } - - inline vector& operator= (const vector& other) - { - assign(other); - return *this; - } - - inline const T* begin() const { return m_p; } - T* begin() { return m_p; } - - inline const T* end() const { return m_p + m_size; } - T* end() { return m_p + m_size; } - - inline bool empty() const { return !m_size; } - inline uint32 size() const { return m_size; } - inline uint32 capacity() const { return m_capacity; } - - inline const T& operator[] (uint32 i) const { CRND_ASSERT(i < m_size); return m_p[i]; } - inline T& operator[] (uint32 i) { CRND_ASSERT(i < m_size); return m_p[i]; } - - inline const T& front() const { CRND_ASSERT(m_size); return m_p[0]; } - inline T& front() { CRND_ASSERT(m_size); return m_p[0]; } - - inline const T& back() const { CRND_ASSERT(m_size); return m_p[m_size - 1]; } - inline T& back() { CRND_ASSERT(m_size); return m_p[m_size - 1]; } - - inline void clear() - { - if (m_p) - { - scalar_type::destruct_array(m_p, m_size); - crnd_free(m_p); - m_p = NULL; - m_size = 0; - m_capacity = 0; - } - - m_alloc_failed = false; - } - - inline bool reserve(uint32 new_capacity) - { - if (!increase_capacity(new_capacity, false)) - return false; - - return true; - } - - inline bool resize(uint32 new_size) - { - if (m_size != new_size) - { - if (new_size < m_size) - scalar_type::destruct_array(m_p + new_size, m_size - new_size); - else - { - if (new_size > m_capacity) - { - if (!increase_capacity(new_size, new_size == (m_size + 1))) - return false; - } - - scalar_type::construct_array(m_p + m_size, new_size - m_size); - } - - m_size = new_size; - } - - return true; - } - - inline bool push_back(const T& obj) - { - CRND_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size))); - - if (m_size >= m_capacity) - { - if (!increase_capacity(m_size + 1, true)) - return false; - } - - scalar_type::construct(m_p + m_size, obj); - m_size++; - - return true; - } - - inline void pop_back() - { - CRND_ASSERT(m_size); - - if (m_size) - { - m_size--; - scalar_type::destruct(&m_p[m_size]); - } - } - - inline void insert(uint32 index, const T* p, uint32 n) - { - CRND_ASSERT(index <= m_size); - if (!n) - return; - - const uint32 orig_size = m_size; - resize(m_size + n); - - const T* pSrc = m_p + orig_size - 1; - T* pDst = const_cast(pSrc) + n; - - const uint32 num_to_move = orig_size - index; - - for (uint32 i = 0; i < num_to_move; i++) - { - CRND_ASSERT((pDst - m_p) < (int)m_size); - *pDst-- = *pSrc--; - } - - pSrc = p; - pDst = m_p + index; - - for (uint32 i = 0; i < n; i++) - { - CRND_ASSERT((pDst - m_p) < (int)m_size); - *pDst++ = *p++; - } - } - - inline void erase(uint32 start, uint32 n) - { - CRND_ASSERT((start + n) <= m_size); - - if (!n) - return; - - const uint32 num_to_move = m_size - (start + n); - - T* pDst = m_p + start; - T* pDst_end = pDst + num_to_move; - const T* pSrc = m_p + start + n; - - while (pDst != pDst_end) - *pDst++ = *pSrc++; - - scalar_type::destruct_array(pDst_end, n); - - m_size -= n; - } - - inline void erase(uint32 index) - { - erase(index, 1); - } - - inline void erase(T* p) - { - CRND_ASSERT((p >= m_p) && (p < (m_p + m_size))); - erase(p - m_p); - } - - inline bool operator== (const vector& rhs) const - { - if (m_size != rhs.m_size) - return false; - else if (m_size) - { - if (scalar_type::cFlag) - return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0; - else - { - const T* pSrc = m_p; - const T* pDst = rhs.m_p; - for (uint32 i = m_size; i; i--) - if (!(*pSrc++ == *pDst++)) - return false; - } - } - - return true; - } - - inline bool operator< (const vector& rhs) const - { - const uint32 min_size = math::minimum(m_size, rhs.m_size); - - const T* pSrc = m_p; - const T* pSrc_end = m_p + min_size; - const T* pDst = rhs.m_p; - - while ((pSrc < pSrc_end) && (*pSrc == *pDst)) - { - pSrc++; - pDst++; - } - - if (pSrc < pSrc_end) - return *pSrc < *pDst; - - return m_size < rhs.m_size; - } - - void swap(vector& other) - { - utils::swap(m_p, other.m_p); - utils::swap(m_size, other.m_size); - utils::swap(m_capacity, other.m_capacity); - } - - private: - T* m_p; - uint32 m_size; - uint32 m_capacity; - bool m_alloc_failed; - - template struct is_vector { enum { cFlag = false }; }; - template struct is_vector< vector > { enum { cFlag = true }; }; - - static void object_mover(void* pDst_void, void* pSrc_void, uint32 num) - { - T* pSrc = static_cast(pSrc_void); - T* const pSrc_end = pSrc + num; - T* pDst = static_cast(pDst_void); - - while (pSrc != pSrc_end) - { - helpers::construct(pDst, *pSrc); - pSrc->~T(); - pSrc++; - pDst++; - } - } - - inline bool increase_capacity(uint32 min_new_capacity, bool grow_hint) - { - if (!reinterpret_cast(this)->increase_capacity( - min_new_capacity, grow_hint, sizeof(T), - ((scalar_type::cFlag) || (is_vector::cFlag) || (bitwise_movable::cFlag) || CRND_IS_POD(T)) ? NULL : object_mover)) - { - m_alloc_failed = true; - return false; - } - return true; - } - }; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - extern void vector_test(); - -} // namespace crnd - -// File: crnd_private.h -namespace crnd -{ - const crn_header* crnd_get_header(crn_header& header, const void* pData, uint32 data_size); - -} // namespace crnd - -// File: checksum.h -namespace crnd -{ - // crc16() intended for small buffers - doesn't use an acceleration table. - const uint16 cInitCRC16 = 0; - uint16 crc16(const void* pBuf, uint32 len, uint16 crc = cInitCRC16); - -} // namespace crnd - -// File: crnd_color.h -namespace crnd -{ - template struct color_quad_component_traits - { - enum - { - cSigned = false, - cFloat = false, - cMin = cUINT8_MIN, - cMax = cUINT8_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = true, - cFloat = false, - cMin = cINT16_MIN, - cMax = cINT16_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = false, - cFloat = false, - cMin = cUINT16_MIN, - cMax = cUINT16_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = true, - cFloat = false, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = false, - cFloat = false, - cMin = cUINT32_MIN, - cMax = cUINT32_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = false, - cFloat = true, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; - }; - - template<> struct color_quad_component_traits - { - enum - { - cSigned = false, - cFloat = true, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; - }; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union -#pragma warning(disable:4127) // warning C4127: conditional expression is constant -#endif - - template - class color_quad : public helpers::rel_ops > - { - static parameter_type clamp(parameter_type v) - { - if (component_traits::cFloat) - return v; - else - { - if (v < component_traits::cMin) - return component_traits::cMin; - else if (v > component_traits::cMax) - return component_traits::cMax; - return v; - } - } - - public: - typedef component_type component_t; - typedef parameter_type parameter_t; - typedef color_quad_component_traits component_traits; - - enum { cNumComps = 4 }; - - union - { - struct - { - component_type r; - component_type g; - component_type b; - component_type a; - }; - - component_type c[cNumComps]; - }; - - inline color_quad() - { - } - - inline color_quad(eClear) : - r(0), g(0), b(0), a(0) - { - } - - inline color_quad(const color_quad& other) : - r(other.r), g(other.g), b(other.b), a(other.a) - { - } - - inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax) - { - set(y, alpha); - } - - inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) - { - set(red, green, blue, alpha); - } - - template - inline color_quad(const color_quad& other) : - r(clamp(other.r)), g(clamp(other.g)), b(clamp(other.b)), a(clamp(other.a)) - { - } - - inline void clear() - { - r = 0; - g = 0; - b = 0; - a = 0; - } - - inline color_quad& operator= (const color_quad& other) - { - r = other.r; - g = other.g; - b = other.b; - a = other.a; - return *this; - } - - template - inline color_quad& operator=(const color_quad& other) - { - r = clamp(other.r); - g = clamp(other.g); - b = clamp(other.b); - a = clamp(other.a); - return *this; - } - - inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax) - { - y = clamp(y); - r = static_cast(y); - g = static_cast(y); - b = static_cast(y); - a = static_cast(alpha); - return *this; - } - - inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) - { - r = static_cast(clamp(red)); - g = static_cast(clamp(green)); - b = static_cast(clamp(blue)); - a = static_cast(clamp(alpha)); - return *this; - } - - inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha) - { - r = static_cast(red); - g = static_cast(green); - b = static_cast(blue); - a = static_cast(alpha); - return *this; - } - - inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue) - { - r = static_cast(red); - g = static_cast(green); - b = static_cast(blue); - return *this; - } - - static inline parameter_type get_min_comp() { return component_traits::cMin; } - static inline parameter_type get_max_comp() { return component_traits::cMax; } - static inline bool get_comps_are_signed() { return component_traits::cSigned; } - - inline component_type operator[] (uint32 i) const { CRND_ASSERT(i < cNumComps); return c[i]; } - inline component_type& operator[] (uint32 i) { CRND_ASSERT(i < cNumComps); return c[i]; } - - inline color_quad& set_component(uint32 i, parameter_type f) - { - CRND_ASSERT(i < cNumComps); - - c[i] = static_cast(clamp(f)); - - return *this; - } - - inline color_quad& clamp(const color_quad& l, const color_quad& h) - { - for (uint32 i = 0; i < cNumComps; i++) - c[i] = static_cast(math::clamp(c[i], l[i], h[i])); - return *this; - } - - inline color_quad& clamp(parameter_type l, parameter_type h) - { - for (uint32 i = 0; i < cNumComps; i++) - c[i] = static_cast(math::clamp(c[i], l, h)); - return *this; - } - - // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y). - inline parameter_type get_luma() const - { - return static_cast((19595U * r + 38470U * g + 7471U * b + 32768) >> 16U); - } - - // Returns REC 709 luma. - inline parameter_type get_luma_rec709() const - { - return static_cast((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U); - } - - inline uint32 squared_distance(const color_quad& c, bool alpha = true) const - { - return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0); - } - - inline bool rgb_equals(const color_quad& rhs) const - { - return (r == rhs.r) && (g == rhs.g) && (b == rhs.b); - } - - inline bool operator== (const color_quad& rhs) const - { - return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a); - } - - inline bool operator< (const color_quad& rhs) const - { - for (uint32 i = 0; i < cNumComps; i++) - { - if (c[i] < rhs.c[i]) - return true; - else if (!(c[i] == rhs.c[i])) - return false; - } - return false; - } - - inline color_quad& operator+= (const color_quad& other) - { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] + other.c[i])); - return *this; - } - - inline color_quad& operator-= (const color_quad& other) - { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] - other.c[i])); - return *this; - } - - inline color_quad& operator*= (parameter_type v) - { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] * v)); - return *this; - } - - inline color_quad& operator/= (parameter_type v) - { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(c[i] / v); - return *this; - } - - inline color_quad get_swizzled(uint32 x, uint32 y, uint32 z, uint32 w) const - { - CRND_ASSERT((x | y | z | w) < 4); - return color_quad(c[x], c[y], c[z], c[w]); - } - - inline friend color_quad operator+ (const color_quad& lhs, const color_quad& rhs) - { - color_quad result(lhs); - result += rhs; - return result; - } - - inline friend color_quad operator- (const color_quad& lhs, const color_quad& rhs) - { - color_quad result(lhs); - result -= rhs; - return result; - } - - inline friend color_quad operator* (const color_quad& lhs, parameter_type v) - { - color_quad result(lhs); - result *= v; - return result; - } - - friend inline color_quad operator/ (const color_quad& lhs, parameter_type v) - { - color_quad result(lhs); - result /= v; - return result; - } - - friend inline color_quad operator* (parameter_type v, const color_quad& rhs) - { - color_quad result(rhs); - result *= v; - return result; - } - - inline uint32 get_min_component_index(bool alpha = true) const - { - uint32 index = 0; - uint32 limit = alpha ? cNumComps : (cNumComps - 1); - for (uint32 i = 1; i < limit; i++) - if (c[i] < c[index]) - index = i; - return index; - } - - inline uint32 get_max_component_index(bool alpha = true) const - { - uint32 index = 0; - uint32 limit = alpha ? cNumComps : (cNumComps - 1); - for (uint32 i = 1; i < limit; i++) - if (c[i] > c[index]) - index = i; - return index; - } - - inline void get_float4(float* pDst) - { - for (uint32 i = 0; i < 4; i++) - pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin); - } - - inline void get_float3(float* pDst) - { - for (uint32 i = 0; i < 3; i++) - pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin); - } - - static inline color_quad make_black() - { - return color_quad(0, 0, 0, component_traits::cMax); - } - - static inline color_quad make_white() - { - return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax); - } - }; // class color_quad - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - template - struct scalar_type< color_quad > - { - enum { cFlag = true }; - static inline void construct(color_quad* p) { } - static inline void construct(color_quad* p, const color_quad& init) { memcpy(p, &init, sizeof(color_quad)); } - static inline void construct_array(color_quad* p, uint32 n) { p, n; } - static inline void destruct(color_quad* p) { p; } - static inline void destruct_array(color_quad* p, uint32 n) { p, n; } - }; - - typedef color_quad color_quad_u8; - typedef color_quad color_quad_i16; - typedef color_quad color_quad_u16; - typedef color_quad color_quad_i32; - typedef color_quad color_quad_u32; - typedef color_quad color_quad_f; - typedef color_quad color_quad_d; - -} // namespace crnd - -// File: crnd_dxt.h -namespace crnd -{ - enum dxt_format - { - cDXTInvalid = -1, - - // cDXT1/1A must appear first! - cDXT1, - cDXT1A, - - cDXT3, - cDXT5, - cDXT5A, - - cDXN_XY, // inverted relative to standard ATI2, 360's DXN - cDXN_YX // standard ATI2 - }; - - enum dxt_constants - { - cDXTBlockShift = 2U, - cDXTBlockSize = 1U << cDXTBlockShift, - - cDXT1BytesPerBlock = 8U, - cDXT5NBytesPerBlock = 16U, - - cDXT1SelectorBits = 2U, - cDXT1SelectorValues = 1U << cDXT1SelectorBits, - cDXT1SelectorMask = cDXT1SelectorValues - 1U, - - cDXT5SelectorBits = 3U, - cDXT5SelectorValues = 1U << cDXT5SelectorBits, - cDXT5SelectorMask = cDXT5SelectorValues - 1U - }; - - const float cDXT1MaxLinearValue = 3.0f; - const float cDXT1InvMaxLinearValue = 1.0f/3.0f; - - const float cDXT5MaxLinearValue = 7.0f; - const float cDXT5InvMaxLinearValue = 1.0f/7.0f; - - // Converts DXT1 raw color selector index to a linear value. - extern const uint8 g_dxt1_to_linear[cDXT1SelectorValues]; - - // Converts DXT5 raw alpha selector index to a linear value. - extern const uint8 g_dxt5_to_linear[cDXT5SelectorValues]; - - // Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear). - extern const uint8 g_dxt1_from_linear[cDXT1SelectorValues]; - - // Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear). - extern const uint8 g_dxt5_from_linear[cDXT5SelectorValues]; - - extern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues]; - extern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues]; - - struct dxt1_block - { - uint8 m_low_color[2]; - uint8 m_high_color[2]; - - enum { cNumSelectorBytes = 4 }; - uint8 m_selectors[cNumSelectorBytes]; - - inline void clear() - { - utils::zero_this(this); - } - - // These methods assume the in-memory rep is in LE byte order. - inline uint32 get_low_color() const - { - return m_low_color[0] | (m_low_color[1] << 8U); - } - - inline uint32 get_high_color() const - { - return m_high_color[0] | (m_high_color[1] << 8U); - } - - inline void set_low_color(uint16 c) - { - m_low_color[0] = static_cast(c & 0xFF); - m_low_color[1] = static_cast((c >> 8) & 0xFF); - } - - inline void set_high_color(uint16 c) - { - m_high_color[0] = static_cast(c & 0xFF); - m_high_color[1] = static_cast((c >> 8) & 0xFF); - } - - inline uint32 get_selector(uint32 x, uint32 y) const - { - CRND_ASSERT((x < 4U) && (y < 4U)); - return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; - } - - inline void set_selector(uint32 x, uint32 y, uint32 val) - { - CRND_ASSERT((x < 4U) && (y < 4U) && (val < 4U)); - - m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); - m_selectors[y] |= (val << (x * cDXT1SelectorBits)); - } - - static uint16 pack_color(const color_quad_u8& color, bool scaled, uint32 bias = 127U); - static uint16 pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias = 127U); - - static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint32 alpha = 255U); - static void unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled); - - static uint32 get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1); - static uint32 get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1); - // pDst must point to an array at least cDXT1SelectorValues long. - static uint32 get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1); - - static color_quad_u8 unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha = 255U); - static uint32 pack_endpoints(uint32 lo, uint32 hi); - }; - - CRND_DEFINE_BITWISE_MOVABLE(dxt1_block); - - struct dxt3_block - { - enum { cNumAlphaBytes = 8 }; - uint8 m_alpha[cNumAlphaBytes]; - - void set_alpha(uint32 x, uint32 y, uint32 value, bool scaled); - uint32 get_alpha(uint32 x, uint32 y, bool scaled) const; - }; - - CRND_DEFINE_BITWISE_MOVABLE(dxt3_block); - - struct dxt5_block - { - uint8 m_endpoints[2]; - - enum { cNumSelectorBytes = 6 }; - uint8 m_selectors[cNumSelectorBytes]; - - inline void clear() - { - utils::zero_this(this); - } - - inline uint32 get_low_alpha() const - { - return m_endpoints[0]; - } - - inline uint32 get_high_alpha() const - { - return m_endpoints[1]; - } - - inline void set_low_alpha(uint32 i) - { - CRND_ASSERT(i <= cUINT8_MAX); - m_endpoints[0] = static_cast(i); - } - - inline void set_high_alpha(uint32 i) - { - CRND_ASSERT(i <= cUINT8_MAX); - m_endpoints[1] = static_cast(i); - } - - uint32 get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); } - - uint32 get_selectors_as_word(uint32 index) { CRND_ASSERT(index < 3); return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); } - - inline uint32 get_selector(uint32 x, uint32 y) const - { - CRND_ASSERT((x < 4U) && (y < 4U)); - - uint32 selector_index = (y * 4) + x; - uint32 bit_index = selector_index * cDXT5SelectorBits; - - uint32 byte_index = bit_index >> 3; - uint32 bit_ofs = bit_index & 7; - - uint32 v = m_selectors[byte_index]; - if (byte_index < (cNumSelectorBytes - 1)) - v |= (m_selectors[byte_index + 1] << 8); - - return (v >> bit_ofs) & 7; - } - - inline void set_selector(uint32 x, uint32 y, uint32 val) - { - CRND_ASSERT((x < 4U) && (y < 4U) && (val < 8U)); - - uint32 selector_index = (y * 4) + x; - uint32 bit_index = selector_index * cDXT5SelectorBits; - - uint32 byte_index = bit_index >> 3; - uint32 bit_ofs = bit_index & 7; - - uint32 v = m_selectors[byte_index]; - if (byte_index < (cNumSelectorBytes - 1)) - v |= (m_selectors[byte_index + 1] << 8); - - v &= (~(7 << bit_ofs)); - v |= (val << bit_ofs); - - m_selectors[byte_index] = static_cast(v); - if (byte_index < (cNumSelectorBytes - 1)) - m_selectors[byte_index + 1] = static_cast(v >> 8); - } - - // Results written to alpha channel. - static uint32 get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h); - static uint32 get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h); - static uint32 get_block_values(color_quad_u8* pDst, uint32 l, uint32 h); - - static uint32 get_block_values6(uint32* pDst, uint32 l, uint32 h); - static uint32 get_block_values8(uint32* pDst, uint32 l, uint32 h); - // pDst must point to an array at least cDXT5SelectorValues long. - static uint32 get_block_values(uint32* pDst, uint32 l, uint32 h); - - static uint32 unpack_endpoint(uint32 packed, uint32 index); - static uint32 pack_endpoints(uint32 lo, uint32 hi); - }; - - CRND_DEFINE_BITWISE_MOVABLE(dxt5_block); - -} // namespace crnd - -// File: crnd_dxt_hc_common.h -namespace crnd -{ - struct chunk_tile_desc - { - // These values are in pixels, and always a multiple of cBlockPixelWidth/cBlockPixelHeight. - uint32 m_x_ofs; - uint32 m_y_ofs; - uint32 m_width; - uint32 m_height; - uint32 m_layout_index; - }; - - struct chunk_encoding_desc - { - uint32 m_num_tiles; - chunk_tile_desc m_tiles[4]; - }; - - const uint32 cChunkPixelWidth = 8; - const uint32 cChunkPixelHeight = 8; - const uint32 cChunkBlockWidth = 2; - const uint32 cChunkBlockHeight = 2; - - const uint32 cChunkMaxTiles = 4; - - const uint32 cBlockPixelWidthShift = 2; - const uint32 cBlockPixelHeightShift = 2; - - const uint32 cBlockPixelWidth = 4; - const uint32 cBlockPixelHeight = 4; - - const uint32 cNumChunkEncodings = 8; - extern chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings]; - - const uint32 cNumChunkTileLayouts = 9; - const uint32 cFirst4x4ChunkTileLayout = 5; - extern chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts]; - -} // namespace crnd - -// File: crnd_prefix_coding.h -#ifdef _XBOX -#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 1 -#else -#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 0 -#endif - -namespace crnd -{ - namespace prefix_coding - { - const uint32 cMaxExpectedCodeSize = 16; - const uint32 cMaxSupportedSyms = 8192; - const uint32 cMaxTableBits = 11; - - class decoder_tables - { - public: - inline decoder_tables() : - m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) - { - } - - inline decoder_tables(const decoder_tables& other) : - m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) - { - *this = other; - } - - decoder_tables& operator= (const decoder_tables& other) - { - if (this == &other) - return *this; - - clear(); - - memcpy(this, &other, sizeof(*this)); - - if (other.m_lookup) - { - m_lookup = crnd_new_array(m_cur_lookup_size); - if (m_lookup) - memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size); - } - - if (other.m_sorted_symbol_order) - { - m_sorted_symbol_order = crnd_new_array(m_cur_sorted_symbol_order_size); - if (m_sorted_symbol_order) - memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size); - } - - return *this; - } - - inline void clear() - { - if (m_lookup) - { - crnd_delete_array(m_lookup); - m_lookup = 0; - m_cur_lookup_size = 0; - } - - if (m_sorted_symbol_order) - { - crnd_delete_array(m_sorted_symbol_order); - m_sorted_symbol_order = NULL; - m_cur_sorted_symbol_order_size = 0; - } - } - - inline ~decoder_tables() - { - if (m_lookup) - crnd_delete_array(m_lookup); - - if (m_sorted_symbol_order) - crnd_delete_array(m_sorted_symbol_order); - } - - bool init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits); - - // DO NOT use any complex classes here - it is bitwise copied. - - uint32 m_num_syms; - uint32 m_total_used_syms; - uint32 m_table_bits; - uint32 m_table_shift; - uint32 m_table_max_code; - uint32 m_decode_start_code_size; - - uint8 m_min_code_size; - uint8 m_max_code_size; - - uint32 m_max_codes[cMaxExpectedCodeSize + 1]; - int32 m_val_ptrs[cMaxExpectedCodeSize + 1]; - - uint32 m_cur_lookup_size; - uint32* m_lookup; - - uint32 m_cur_sorted_symbol_order_size; - uint16* m_sorted_symbol_order; - - inline uint32 get_unshifted_max_code(uint32 len) const - { - CRND_ASSERT( (len >= 1) && (len <= cMaxExpectedCodeSize) ); - uint32 k = m_max_codes[len - 1]; - if (!k) - return crnd::cUINT32_MAX; - return (k - 1) >> (16 - len); - } - }; - - } // namespace prefix_coding - -} // namespace crnd - -// File: crnd_symbol_codec.h -namespace crnd -{ - class static_huffman_data_model - { - public: - static_huffman_data_model(); - static_huffman_data_model(const static_huffman_data_model& other); - ~static_huffman_data_model(); - - static_huffman_data_model& operator= (const static_huffman_data_model& rhs); - - bool init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit); - void clear(); - - inline bool is_valid() const { return m_pDecode_tables != NULL; } - - inline uint32 get_total_syms() const { return m_total_syms; } - - inline uint32 get_code_size(uint32 sym) const { return m_code_sizes[sym]; } - - inline const uint8* get_code_sizes() const { return m_code_sizes.empty() ? NULL : &m_code_sizes[0]; } - - public: - uint32 m_total_syms; - crnd::vector m_code_sizes; - prefix_coding::decoder_tables* m_pDecode_tables; - - private: - bool prepare_decoder_tables(); - uint compute_decoder_table_bits() const; - - friend class symbol_codec; - }; - - class symbol_codec - { - public: - symbol_codec(); - - bool start_decoding(const uint8* pBuf, uint32 buf_size); - bool decode_receive_static_data_model(static_huffman_data_model& model); - - uint32 decode_bits(uint32 num_bits); - uint32 decode(const static_huffman_data_model& model); - - uint64 stop_decoding(); - - public: - const uint8* m_pDecode_buf; - const uint8* m_pDecode_buf_next; - const uint8* m_pDecode_buf_end; - uint32 m_decode_buf_size; - - typedef uint32 bit_buf_type; - enum { cBitBufSize = 32U }; - bit_buf_type m_bit_buf; - - int m_bit_count; - - private: - void get_bits_init(); - uint32 get_bits(uint32 num_bits); - }; - -} // namespace crnd - -#define CRND_HUFF_DECODE_BEGIN(x) -#define CRND_HUFF_DECODE_END(x) -#define CRND_HUFF_DECODE(codec, model, symbol) symbol = codec.decode(model); - -namespace crnd -{ - void crnd_assert(const char* pExp, const char* pFile, unsigned line) - { - char buf[512]; - -#if defined(_WIN32) && defined(_MSC_VER) - sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp); -#else - sprintf(buf, "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp); -#endif - - crnd_output_debug_string(buf); - - puts(buf); - - if (crnd_is_debugger_present()) - crnd_debug_break(); - } - - void crnd_trace(const char* pFmt, va_list args) - { - if (crnd_is_debugger_present()) - { - char buf[512]; -#if defined(_WIN32) && defined(_MSC_VER) - vsprintf_s(buf, sizeof(buf), pFmt, args); -#else - vsprintf(buf, pFmt, args); -#endif - - crnd_output_debug_string(buf); - } - }; - - void crnd_trace(const char* pFmt, ...) - { - va_list args; - va_start(args, pFmt); - crnd_trace(pFmt, args); - va_end(args); - }; - -} // namespace crnd - -// File: checksum.cpp -// From the public domain stb.h header. -namespace crnd -{ - uint16 crc16(const void* pBuf, uint32 len, uint16 crc) - { - crc = ~crc; - - const uint8* p = reinterpret_cast(pBuf); - while (len) - { - const uint16 q = *p++ ^ (crc >> 8U); - crc <<= 8U; - - uint16 r = (q >> 4U) ^ q; - crc ^= r; - r <<= 5U; - crc ^= r; - r <<= 7U; - crc ^= r; - - len--; - } - - return static_cast(~crc); - } - -} // namespace crnd - - -// File: crnd_vector.cpp -namespace crnd -{ - bool elemental_vector::increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pMover) - { - CRND_ASSERT(m_size <= m_capacity); - CRND_ASSERT(min_new_capacity < (0x7FFF0000U / element_size)); - - if (m_capacity >= min_new_capacity) - return true; - - uint32 new_capacity = min_new_capacity; - if ((grow_hint) && (!math::is_power_of_2(new_capacity))) - new_capacity = math::next_pow2(new_capacity); - - CRND_ASSERT(new_capacity && (new_capacity > m_capacity)); - - const uint32 desired_size = element_size * new_capacity; - size_t actual_size; - if (!pMover) - { - void* new_p = crnd_realloc(m_p, desired_size, &actual_size, true); - if (!new_p) - return false; - m_p = new_p; - } - else - { - void* new_p = crnd_malloc(desired_size, &actual_size); - if (!new_p) - return false; - - (*pMover)(new_p, m_p, m_size); - - if (m_p) - crnd_free(m_p); - - m_p = new_p; - } - - if (actual_size > desired_size) - m_capacity = static_cast(actual_size / element_size); - else - m_capacity = new_capacity; - - return true; - } - -} // namespace crnd - -// File: crnd_utils.cpp -namespace crnd -{ - namespace utils - { - uint32 compute_max_mips(uint32 width, uint32 height) - { - if ((width | height) == 0) - return 0; - - uint32 num_mips = 1; - - while ((width > 1U) || (height > 1U)) - { - width >>= 1U; - height >>= 1U; - num_mips++; - } - - return num_mips; - } - - } // namespace utils - -} // namespace crnd - -// File: crnd_prefix_coding.cpp -namespace crnd -{ - namespace prefix_coding - { - bool decoder_tables::init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits) - { - uint32 min_codes[cMaxExpectedCodeSize]; - if ((!num_syms) || (table_bits > cMaxTableBits)) - return false; - - m_num_syms = num_syms; - - uint32 num_codes[cMaxExpectedCodeSize + 1]; - utils::zero_object(num_codes); - - for (uint32 i = 0; i < num_syms; i++) - { - uint32 c = pCodesizes[i]; - if (c) - num_codes[c]++; - } - - uint32 sorted_positions[cMaxExpectedCodeSize + 1]; - - uint32 cur_code = 0; - - uint32 total_used_syms = 0; - uint32 max_code_size = 0; - uint32 min_code_size = cUINT32_MAX; - for (uint32 i = 1; i <= cMaxExpectedCodeSize; i++) - { - const uint32 n = num_codes[i]; - - if (!n) - m_max_codes[i - 1] = 0;//UINT_MAX; - else - { - min_code_size = math::minimum(min_code_size, i); - max_code_size = math::maximum(max_code_size, i); - - min_codes[i - 1] = cur_code; - - m_max_codes[i - 1] = cur_code + n - 1; - m_max_codes[i - 1] = 1 + ((m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1)); - - m_val_ptrs[i - 1] = total_used_syms; - - sorted_positions[i] = total_used_syms; - - cur_code += n; - total_used_syms += n; - } - - cur_code <<= 1; - } - - m_total_used_syms = total_used_syms; - - if (total_used_syms > m_cur_sorted_symbol_order_size) - { - m_cur_sorted_symbol_order_size = total_used_syms; - - if (!math::is_power_of_2(total_used_syms)) - m_cur_sorted_symbol_order_size = math::minimum(num_syms, math::next_pow2(total_used_syms)); - - if (m_sorted_symbol_order) - crnd_delete_array(m_sorted_symbol_order); - - m_sorted_symbol_order = crnd_new_array(m_cur_sorted_symbol_order_size); - if (!m_sorted_symbol_order) - return false; - } - - m_min_code_size = static_cast(min_code_size); - m_max_code_size = static_cast(max_code_size); - - for (uint32 i = 0; i < num_syms; i++) - { - uint32 c = pCodesizes[i]; - if (c) - { - CRND_ASSERT(num_codes[c]); - - uint32 sorted_pos = sorted_positions[c]++; - - CRND_ASSERT(sorted_pos < total_used_syms); - - m_sorted_symbol_order[sorted_pos] = static_cast(i); - } - } - - if (table_bits <= m_min_code_size) - table_bits = 0; - m_table_bits = table_bits; - - if (table_bits) - { - uint32 table_size = 1 << table_bits; - if (table_size > m_cur_lookup_size) - { - m_cur_lookup_size = table_size; - - if (m_lookup) - crnd_delete_array(m_lookup); - - m_lookup = crnd_new_array(table_size); - if (!m_lookup) - return false; - } - - memset(m_lookup, 0xFF, (uint)sizeof(m_lookup[0]) * (1UL << table_bits)); - - for (uint32 codesize = 1; codesize <= table_bits; codesize++) - { - if (!num_codes[codesize]) - continue; - - const uint32 fillsize = table_bits - codesize; - const uint32 fillnum = 1 << fillsize; - - const uint32 min_code = min_codes[codesize - 1]; - const uint32 max_code = get_unshifted_max_code(codesize); - const uint32 val_ptr = m_val_ptrs[codesize - 1]; - - for (uint32 code = min_code; code <= max_code; code++) - { - const uint32 sym_index = m_sorted_symbol_order[ val_ptr + code - min_code ]; - CRND_ASSERT( pCodesizes[sym_index] == codesize ); - - for (uint32 j = 0; j < fillnum; j++) - { - const uint32 t = j + (code << fillsize); - - CRND_ASSERT(t < (1U << table_bits)); - - CRND_ASSERT(m_lookup[t] == cUINT32_MAX); - - m_lookup[t] = sym_index | (codesize << 16U); - } - } - } - } - - for (uint32 i = 0; i < cMaxExpectedCodeSize; i++) - m_val_ptrs[i] -= min_codes[i]; - - m_table_max_code = 0; - m_decode_start_code_size = m_min_code_size; - - if (table_bits) - { - uint32 i; - for (i = table_bits; i >= 1; i--) - { - if (num_codes[i]) - { - m_table_max_code = m_max_codes[i - 1]; - break; - } - } - if (i >= 1) - { - m_decode_start_code_size = table_bits + 1; - for (uint32 j = table_bits + 1; j <= max_code_size; j++) - { - if (num_codes[j]) - { - m_decode_start_code_size = j; - break; - } - } - } - } - - // sentinels - m_max_codes[cMaxExpectedCodeSize] = cUINT32_MAX; - m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF; - - m_table_shift = 32 - m_table_bits; - return true; - } - - } // namespace prefix_codig - -} // namespace crnd - -// File: crnd_platform.cpp -namespace crnd -{ - bool crnd_is_debugger_present() - { -#ifdef CRND_DEVEL - return IsDebuggerPresent() != 0; -#else - return false; -#endif - } - - void crnd_debug_break() - { -#ifdef CRND_DEVEL - DebugBreak(); -#endif - } - - void crnd_output_debug_string(const char* p) - { - p; -#ifdef CRND_DEVEL - OutputDebugStringA(p); -#endif - } - -} // namespace crnd - -// File: crnd_mem.cpp -namespace crnd -{ - const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U; - - static void* crnd_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data) - { - pUser_data; - - void* p_new; - - if (!p) - { - p_new = ::malloc(size); - - if (pActual_size) - { -#ifdef _WIN32 - *pActual_size = p_new ? ::_msize(p_new) : 0; -#else - *pActual_size = p_new ? malloc_usable_size(p_new) : 0; -#endif - } - } - else if (!size) - { - ::free(p); - p_new = NULL; - - if (pActual_size) - *pActual_size = 0; - } - else - { - void* p_final_block = p; -#ifdef _WIN32 - p_new = ::_expand(p, size); -#else - p_new = NULL; -#endif - - if (p_new) - p_final_block = p_new; - else if (movable) - { - p_new = ::realloc(p, size); - - if (p_new) - p_final_block = p_new; - } - - if (pActual_size) - { -#ifdef _WIN32 - *pActual_size = ::_msize(p_final_block); -#else - *pActual_size = ::malloc_usable_size(p_final_block); -#endif - } - } - - return p_new; - } - - static size_t crnd_default_msize(void* p, void* pUser_data) - { - pUser_data; -#ifdef _WIN32 - return p ? _msize(p) : 0; -#else - return p ? malloc_usable_size(p) : 0; -#endif - } - - static crnd_realloc_func g_pRealloc = crnd_default_realloc; - static crnd_msize_func g_pMSize = crnd_default_msize; - static void* g_pUser_data; - - void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data) - { - if ((!pRealloc) || (!pMSize)) - { - g_pRealloc = crnd_default_realloc; - g_pMSize = crnd_default_msize; - g_pUser_data = NULL; - } - else - { - g_pRealloc = pRealloc; - g_pMSize = pMSize; - g_pUser_data = pUser_data; - } - } - - static inline void crnd_mem_error(const char* p_msg) - { - crnd_assert(p_msg, __FILE__, __LINE__); - } - - void* crnd_malloc(size_t size, size_t* pActual_size) - { - size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U); - if (!size) - size = sizeof(uint32); - - if (size > MAX_POSSIBLE_BLOCK_SIZE) - { - crnd_mem_error("crnd_malloc: size too big"); - return NULL; - } - - size_t actual_size = size; - uint8* p_new = static_cast((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data)); - - if (pActual_size) - *pActual_size = actual_size; - - if ((!p_new) || (actual_size < size)) - { - crnd_mem_error("crnd_malloc: out of memory"); - return NULL; - } - - CRND_ASSERT(((uint32)p_new & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0); - - return p_new; - } - - void* crnd_realloc(void* p, size_t size, size_t* pActual_size, bool movable) - { - if ((uint32)reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) - { - crnd_mem_error("crnd_realloc: bad ptr"); - return NULL; - } - - if (size > MAX_POSSIBLE_BLOCK_SIZE) - { - crnd_mem_error("crnd_malloc: size too big"); - return NULL; - } - - size_t actual_size = size; - void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data); - - if (pActual_size) - *pActual_size = actual_size; - - CRND_ASSERT(((uint32)p_new & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0); - - return p_new; - } - - void crnd_free(void* p) - { - if (!p) - return; - - if ((uint32)reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) - { - crnd_mem_error("crnd_free: bad ptr"); - return; - } - - (*g_pRealloc)(p, 0, NULL, true, g_pUser_data); - } - - size_t crnd_msize(void* p) - { - if (!p) - return 0; - - if ((uint32)reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) - { - crnd_mem_error("crnd_msize: bad ptr"); - return 0; - } - - return (*g_pMSize)(p, g_pUser_data); - } - -} // namespace crnd - -// File: crnd_math.cpp -namespace crnd -{ - namespace math - { - uint32 g_bitmasks[32] = - { - 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, - 1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U, - 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, - 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, - 1U << 16U, 1U << 17U, 1U << 18U, 1U << 19U, - 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, - 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, - 1U << 28U, 1U << 29U, 1U << 30U, 1U << 31U - }; - - } // namespace math -} // namespace crnd - -// File: crnd_info.cpp -namespace crnd -{ -#define CRND_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U)) - - uint32 crnd_crn_format_to_fourcc(crn_format fmt) - { - switch (fmt) - { - case cCRNFmtDXT1: return CRND_FOURCC('D', 'X', 'T', '1'); - case cCRNFmtDXT3: return CRND_FOURCC('D', 'X', 'T', '3'); - case cCRNFmtDXT5: return CRND_FOURCC('D', 'X', 'T', '5'); - case cCRNFmtDXN_XY: return CRND_FOURCC('A', '2', 'X', 'Y'); - case cCRNFmtDXN_YX: return CRND_FOURCC('A', 'T', 'I', '2'); - case cCRNFmtDXT5A: return CRND_FOURCC('A', 'T', 'I', '1'); - case cCRNFmtDXT5_CCxY: return CRND_FOURCC('C', 'C', 'x', 'Y'); - case cCRNFmtDXT5_xGxR: return CRND_FOURCC('x', 'G', 'x', 'R'); - case cCRNFmtDXT5_xGBR: return CRND_FOURCC('x', 'G', 'B', 'R'); - case cCRNFmtDXT5_AGBR: return CRND_FOURCC('A', 'G', 'B', 'R'); - case cCRNFmtETC1: return CRND_FOURCC('E', 'T', 'C', '1'); - default: break; - } - CRND_ASSERT(false); - return 0; - } - - crn_format crnd_get_fundamental_dxt_format(crn_format fmt) - { - switch (fmt) - { - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGxR: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - return cCRNFmtDXT5; - default: break; - } - return fmt; - } - - uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt) - { - switch (fmt) - { - case cCRNFmtDXT1: - case cCRNFmtDXT5A: - case cCRNFmtETC1: - return 4; - case cCRNFmtDXT3: - case cCRNFmtDXT5: - case cCRNFmtDXN_XY: - case cCRNFmtDXN_YX: - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGxR: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - return 8; - default: break; - } - CRND_ASSERT(false); - return 0; - } - - uint32 crnd_get_bytes_per_dxt_block(crn_format fmt) - { - return (crnd_get_crn_format_bits_per_texel(fmt) << 4) >> 3; - } - - // TODO: tmp_header isn't used/This function is a helper to support old headers. - const crn_header* crnd_get_header(crn_header& tmp_header, const void* pData, uint32 data_size) - { - tmp_header; - - if ((!pData) || (data_size < sizeof(crn_header))) - return NULL; - - const crn_header& file_header = *static_cast(pData); - if (file_header.m_sig != crn_header::cCRNSigValue) - return NULL; - - if ((file_header.m_header_size < sizeof(crn_header)) || (data_size < file_header.m_data_size)) - return NULL; - - return &file_header; - } - - bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) - { - if (pFile_info) - { - if (pFile_info->m_struct_size != sizeof(crn_file_info)) - return false; - - memset(&pFile_info->m_struct_size + 1, 0, sizeof(crn_file_info) - sizeof(pFile_info->m_struct_size)); - } - - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return false; - - const uint32 header_crc = crc16(&pHeader->m_data_size, (uint32)(pHeader->m_header_size - ((const uint8*)&pHeader->m_data_size - (const uint8*)pHeader))); - if (header_crc != pHeader->m_header_crc16) - return false; - - const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size); - if (data_crc != pHeader->m_data_crc16) - return false; - - if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6)) - return false; - if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution)) - return false; - if ((pHeader->m_height < 1) || (pHeader->m_height > cCRNMaxLevelResolution)) - return false; - if ((pHeader->m_levels < 1) || (pHeader->m_levels > utils::compute_max_mips(pHeader->m_width, pHeader->m_height))) - return false; - if (((int)pHeader->m_format < cCRNFmtDXT1) || ((int)pHeader->m_format >= cCRNFmtTotal)) - return false; - - if (pFile_info) - { - pFile_info->m_actual_data_size = pHeader->m_data_size; - pFile_info->m_header_size = pHeader->m_header_size; - pFile_info->m_total_palette_size = pHeader->m_color_endpoints.m_size + pHeader->m_color_selectors.m_size + pHeader->m_alpha_endpoints.m_size + pHeader->m_alpha_selectors.m_size; - pFile_info->m_tables_size = pHeader->m_tables_size; - - pFile_info->m_levels = pHeader->m_levels; - - for (uint32 i = 0; i < pHeader->m_levels; i++) - { - uint32 next_ofs = pHeader->m_data_size; - - // assumes the levels are packed together sequentially - if ((i + 1) < pHeader->m_levels) - next_ofs = pHeader->m_level_ofs[i + 1]; - - pFile_info->m_level_compressed_size[i] = next_ofs - pHeader->m_level_ofs[i]; - } - - pFile_info->m_color_endpoint_palette_entries = pHeader->m_color_endpoints.m_num; - pFile_info->m_color_selector_palette_entries = pHeader->m_color_selectors.m_num;; - pFile_info->m_alpha_endpoint_palette_entries = pHeader->m_alpha_endpoints.m_num;; - pFile_info->m_alpha_selector_palette_entries = pHeader->m_alpha_selectors.m_num;; - } - - return true; - } - - bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo) - { - if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo)) - return false; - - if (pInfo->m_struct_size != sizeof(crn_texture_info)) - return false; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return false; - - pInfo->m_width = pHeader->m_width; - pInfo->m_height = pHeader->m_height; - pInfo->m_levels = pHeader->m_levels; - pInfo->m_faces = pHeader->m_faces; - pInfo->m_format = static_cast((uint32)pHeader->m_format); - pInfo->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16; - pInfo->m_userdata0 = pHeader->m_userdata0; - pInfo->m_userdata1 = pHeader->m_userdata1; - - return true; - } - - bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info) - { - if ((!pData) || (data_size < cCRNHeaderMinSize) || (!pLevel_info)) - return false; - - if (pLevel_info->m_struct_size != sizeof(crn_level_info)) - return false; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return false; - - if (level_index >= pHeader->m_levels) - return false; - - uint32 width = math::maximum(1U, pHeader->m_width >> level_index); - uint32 height = math::maximum(1U, pHeader->m_height >> level_index); - - pLevel_info->m_width = width; - pLevel_info->m_height = height; - pLevel_info->m_faces = pHeader->m_faces; - pLevel_info->m_blocks_x = (width + 3) >> 2; - pLevel_info->m_blocks_y = (height + 3) >> 2; - pLevel_info->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16; - pLevel_info->m_format = static_cast((uint32)pHeader->m_format); - - return true; - } - - const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize) - { - if (pSize) - *pSize = 0; - - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return NULL; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return NULL; - - if (level_index >= pHeader->m_levels) - return NULL; - - uint32 cur_level_ofs = pHeader->m_level_ofs[level_index]; - - if (pSize) - { - uint32 next_level_ofs = data_size; - if ((level_index + 1) < (pHeader->m_levels)) - next_level_ofs = pHeader->m_level_ofs[level_index + 1]; - - *pSize = next_level_ofs - cur_level_ofs; - } - - return static_cast(pData) + cur_level_ofs; - } - - uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size) - { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return false; - - uint32 size = pHeader->m_header_size; - - size = math::maximum(size, pHeader->m_color_endpoints.m_ofs + pHeader->m_color_endpoints.m_size); - size = math::maximum(size, pHeader->m_color_selectors.m_ofs + pHeader->m_color_selectors.m_size); - size = math::maximum(size, pHeader->m_alpha_endpoints.m_ofs + pHeader->m_alpha_endpoints.m_size); - size = math::maximum(size, pHeader->m_alpha_selectors.m_ofs + pHeader->m_alpha_selectors.m_size); - size = math::maximum(size, pHeader->m_tables_ofs + pHeader->m_tables_size); - - return size; - } - - bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size) - { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - crn_header tmp_header; - const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size); - if (!pHeader) - return false; - - if (pHeader->m_flags & cCRNHeaderFlagSegmented) - return false; - - const uint actual_base_data_size = crnd_get_segmented_file_size(pData, data_size); - if (base_data_size < actual_base_data_size) - return false; - - memcpy(pBase_data, pData, actual_base_data_size); - - crn_header& new_header = *static_cast(pBase_data); - new_header.m_flags = new_header.m_flags | cCRNHeaderFlagSegmented; - new_header.m_data_size = actual_base_data_size; - - new_header.m_data_crc16 = crc16((const uint8*)pBase_data + new_header.m_header_size, new_header.m_data_size - new_header.m_header_size); - - new_header.m_header_crc16 = crc16(&new_header.m_data_size, new_header.m_header_size - (uint32)((const uint8*)&new_header.m_data_size - (const uint8*)&new_header)); - - CRND_ASSERT(crnd_validate_file(&new_header, actual_base_data_size, NULL)); - - return true; - } - -} // namespace crnd - -// File: symbol_codec.cpp -namespace crnd -{ - static_huffman_data_model::static_huffman_data_model() : -m_total_syms(0), -m_pDecode_tables(NULL) -{ -} - -static_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other) : -m_total_syms(0), -m_pDecode_tables(NULL) -{ - *this = other; -} - -static_huffman_data_model::~static_huffman_data_model() -{ - if (m_pDecode_tables) - crnd_delete(m_pDecode_tables); -} - -static_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs) -{ - if (this == &rhs) - return *this; - - m_total_syms = rhs.m_total_syms; - m_code_sizes = rhs.m_code_sizes; - if (m_code_sizes.get_alloc_failed()) - { - clear(); - return *this; - } - - if (rhs.m_pDecode_tables) - { - if (m_pDecode_tables) - *m_pDecode_tables = *rhs.m_pDecode_tables; - else - m_pDecode_tables = crnd_new(*rhs.m_pDecode_tables); - } - else - { - crnd_delete(m_pDecode_tables); - m_pDecode_tables = NULL; - } - - return *this; -} - -void static_huffman_data_model::clear() -{ - m_total_syms = 0; - m_code_sizes.clear(); - if (m_pDecode_tables) - { - crnd_delete(m_pDecode_tables); - m_pDecode_tables = NULL; - } -} - -bool static_huffman_data_model::init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit) -{ - CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1)); - - code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize); - - if (!m_code_sizes.resize(total_syms)) - return false; - - uint32 min_code_size = cUINT32_MAX; - uint32 max_code_size = 0; - - for (uint32 i = 0; i < total_syms; i++) - { - uint32 s = pCode_sizes[i]; - m_code_sizes[i] = static_cast(s); - min_code_size = math::minimum(min_code_size, s); - max_code_size = math::maximum(max_code_size, s); - } - - if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit)) - return false; - - if (max_code_size > code_size_limit) - return false; - - if (!m_pDecode_tables) - m_pDecode_tables = crnd_new(); - - if (!m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits())) - return false; - - return true; -} - -bool static_huffman_data_model::prepare_decoder_tables() -{ - uint32 total_syms = m_code_sizes.size(); - - CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms)); - - m_total_syms = total_syms; - - if (!m_pDecode_tables) - m_pDecode_tables = crnd_new(); - - return m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits()); -} - -uint static_huffman_data_model::compute_decoder_table_bits() const -{ -#if CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE - return prefix_coding::cMaxTableBits; -#else - uint32 decoder_table_bits = 0; - if (m_total_syms > 16) - decoder_table_bits = static_cast(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits)); - return decoder_table_bits; -#endif -} - -symbol_codec::symbol_codec() : - m_pDecode_buf(NULL), - m_pDecode_buf_next(NULL), - m_pDecode_buf_end(NULL), - m_decode_buf_size(0), - m_bit_buf(0), - m_bit_count(0) -{ -} - -// Code length encoding symbols: -// 0-16 - actual code lengths -const uint32 cMaxCodelengthCodes = 21; - -const uint32 cSmallZeroRunCode = 17; -const uint32 cLargeZeroRunCode = 18; -const uint32 cSmallRepeatCode = 19; -const uint32 cLargeRepeatCode = 20; - -const uint32 cMinSmallZeroRunSize = 3; -const uint32 cMaxSmallZeroRunSize = 10; -const uint32 cMinLargeZeroRunSize = 11; -const uint32 cMaxLargeZeroRunSize = 138; - -const uint32 cSmallMinNonZeroRunSize = 3; -const uint32 cSmallMaxNonZeroRunSize = 6; -const uint32 cLargeMinNonZeroRunSize = 7; -const uint32 cLargeMaxNonZeroRunSize = 70; - -const uint32 cSmallZeroRunExtraBits = 3; -const uint32 cLargeZeroRunExtraBits = 7; -const uint32 cSmallNonZeroRunExtraBits = 2; -const uint32 cLargeNonZeroRunExtraBits = 6; - -static const uint8 g_most_probable_codelength_codes[] = -{ - cSmallZeroRunCode, cLargeZeroRunCode, - cSmallRepeatCode, cLargeRepeatCode, - - 0, 8, - 7, 9, - 6, 10, - 5, 11, - 4, 12, - 3, 13, - 2, 14, - 1, 15, - 16 -}; -const uint32 cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]); - -bool symbol_codec::decode_receive_static_data_model(static_huffman_data_model& model) -{ - const uint32 total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms)); - - if (!total_used_syms) - { - model.clear(); - return true; - } - - if (!model.m_code_sizes.resize(total_used_syms)) - return false; - - memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms); - - const uint32 num_codelength_codes_to_send = decode_bits(5); - if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes)) - return false; - - static_huffman_data_model dm; - if (!dm.m_code_sizes.resize(cMaxCodelengthCodes)) - return false; - - for (uint32 i = 0; i < num_codelength_codes_to_send; i++) - dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast(decode_bits(3)); - - if (!dm.prepare_decoder_tables()) - return false; - - uint32 ofs = 0; - while (ofs < total_used_syms) - { - const uint32 num_remaining = total_used_syms - ofs; - - uint32 code = decode(dm); - if (code <= 16) - model.m_code_sizes[ofs++] = static_cast(code); - else if (code == cSmallZeroRunCode) - { - uint32 len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize; - if (len > num_remaining) - return false; - ofs += len; - } - else if (code == cLargeZeroRunCode) - { - uint32 len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize; - if (len > num_remaining) - return false; - ofs += len; - } - else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode)) - { - uint32 len; - if (code == cSmallRepeatCode) - len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize; - else - len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize; - - if ((!ofs) || (len > num_remaining)) - return false; - const uint32 prev = model.m_code_sizes[ofs - 1]; - if (!prev) - return false; - const uint32 end = ofs + len; - while (ofs < end) - model.m_code_sizes[ofs++] = static_cast(prev); - } - else - { - CRND_ASSERT(0); - return false; - } - } - - if (ofs != total_used_syms) - return false; - - return model.prepare_decoder_tables(); -} - -bool symbol_codec::start_decoding(const uint8* pBuf, uint32 buf_size) -{ - if (!buf_size) - return false; - - m_pDecode_buf = pBuf; - m_pDecode_buf_next = pBuf; - m_decode_buf_size = buf_size; - m_pDecode_buf_end = pBuf + buf_size; - - get_bits_init(); - - return true; -} - -void symbol_codec::get_bits_init() -{ - m_bit_buf = 0; - m_bit_count = 0; -} - -uint32 symbol_codec::decode_bits(uint32 num_bits) -{ - if (!num_bits) - return 0; - - if (num_bits > 16) - { - uint32 a = get_bits(num_bits - 16); - uint32 b = get_bits(16); - - return (a << 16) | b; - } - else - return get_bits(num_bits); -} - -uint32 symbol_codec::get_bits(uint32 num_bits) -{ - CRND_ASSERT(num_bits <= 32U); - - while (m_bit_count < (int)num_bits) - { - bit_buf_type c = 0; - if (m_pDecode_buf_next != m_pDecode_buf_end) - c = *m_pDecode_buf_next++; - - m_bit_count += 8; - CRND_ASSERT(m_bit_count <= cBitBufSize); - - m_bit_buf |= (c << (cBitBufSize - m_bit_count)); - } - - uint32 result = static_cast(m_bit_buf >> (cBitBufSize - num_bits)); - - m_bit_buf <<= num_bits; - m_bit_count -= num_bits; - - return result; -} - -uint32 symbol_codec::decode(const static_huffman_data_model& model) -{ - const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables; - - if (m_bit_count < 24) - { - if (m_bit_count < 16) - { - uint32 c0 = 0, c1 = 0; - const uint8* p = m_pDecode_buf_next; - if (p < m_pDecode_buf_end) c0 = *p++; - if (p < m_pDecode_buf_end) c1 = *p++; - m_pDecode_buf_next = p; - m_bit_count += 16; - uint32 c = (c0 << 8) | c1; - m_bit_buf |= (c << (32 - m_bit_count)); - } - else - { - uint32 c = (m_pDecode_buf_next < m_pDecode_buf_end) ? *m_pDecode_buf_next++ : 0; - m_bit_count += 8; - m_bit_buf |= (c << (32 - m_bit_count)); - } - } - - uint32 k = (m_bit_buf >> 16) + 1; - uint32 sym, len; - - if (k <= pTables->m_table_max_code) - { - uint32 t = pTables->m_lookup[m_bit_buf >> (32 - pTables->m_table_bits)]; - - CRND_ASSERT(t != cUINT32_MAX); - sym = t & cUINT16_MAX; - len = t >> 16; - - CRND_ASSERT(model.m_code_sizes[sym] == len); - } - else - { - len = pTables->m_decode_start_code_size; - - for ( ; ; ) - { - if (k <= pTables->m_max_codes[len - 1]) - break; - len++; - } - - int val_ptr = pTables->m_val_ptrs[len - 1] + (m_bit_buf >> (32 - len)); - - if (((uint32)val_ptr >= model.m_total_syms)) - { - // corrupted stream, or a bug - CRND_ASSERT(0); - return 0; - } - - sym = pTables->m_sorted_symbol_order[val_ptr]; - } - - m_bit_buf <<= len; - m_bit_count -= len; - - return sym; -} - - uint64 symbol_codec::stop_decoding() - { -#if 0 - uint32 i = get_bits(4); - uint32 k = get_bits(3); - i, k; - CRND_ASSERT((i == 15) && (k == 3)); -#endif - - uint64 n = static_cast(m_pDecode_buf_next - m_pDecode_buf); - - return n; - } - -} // namespace crnd - -// File: crnd_dxt_hc_common.cpp -namespace crnd -{ - chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings] = - { - { 1, { { 0, 0, 8, 8, 0 } } }, - - { 2, { { 0, 0, 8, 4, 1 }, { 0, 4, 8, 4, 2 } } }, - { 2, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 8, 4 } } }, - - { 3, { { 0, 0, 8, 4, 1 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } }, - { 3, { { 0, 4, 8, 4, 2 }, { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 } } }, - - { 3, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 4, 6 }, { 4, 4, 4, 4, 8 } } }, - { 3, { { 4, 0, 4, 8, 4 }, { 0, 0, 4, 4, 5 }, { 0, 4, 4, 4, 7 } } }, - - { 4, { { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } } - }; - - chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts] = - { - // 2x2 - { 0, 0, 8, 8, 0 }, - - // 2x1 - { 0, 0, 8, 4, 1 }, - { 0, 4, 8, 4, 2 }, - - // 1x2 - { 0, 0, 4, 8, 3 }, - { 4, 0, 4, 8, 4 }, - - // 1x1 - { 0, 0, 4, 4, 5 }, - { 4, 0, 4, 4, 6 }, - { 0, 4, 4, 4, 7 }, - { 4, 4, 4, 4, 8 } - }; - -} // namespace crnd - -// File: crnd_dxt.cpp -namespace crnd -{ - const uint8 g_dxt1_to_linear[cDXT1SelectorValues] = { 0U, 3U, 1U, 2U }; - const uint8 g_dxt1_from_linear[cDXT1SelectorValues] = { 0U, 2U, 3U, 1U }; - - const uint8 g_dxt5_to_linear[cDXT5SelectorValues] = { 0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U }; - const uint8 g_dxt5_from_linear[cDXT5SelectorValues] = { 0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U }; - - const uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 5, 4, 3, 2, 6, 7 }; - const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 7, 6, 5, 4, 3, 2 }; - - uint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint32 bias) - { - uint32 r = color.r; - uint32 g = color.g; - uint32 b = color.b; - - if (scaled) - { - r = (r * 31U + bias) / 255U; - g = (g * 63U + bias) / 255U; - b = (b * 31U + bias) / 255U; - } - - r = math::minimum(r, 31U); - g = math::minimum(g, 63U); - b = math::minimum(b, 31U); - - return static_cast(b | (g << 5U) | (r << 11U)); - } - - uint16 dxt1_block::pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias) - { - return pack_color(color_quad_u8(r, g, b, 0), scaled, bias); - } - - color_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint32 alpha) - { - uint32 b = packed_color & 31U; - uint32 g = (packed_color >> 5U) & 63U; - uint32 r = (packed_color >> 11U) & 31U; - - if (scaled) - { - b = (b << 3U) | (b >> 2U); - g = (g << 2U) | (g >> 4U); - r = (r << 3U) | (r >> 2U); - } - - return color_quad_u8(r, g, b, alpha); - } - - void dxt1_block::unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled) - { - color_quad_u8 c(unpack_color(packed_color, scaled, 0)); - r = c.r; - g = c.g; - b = c.b; - } - - uint32 dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1) - { - color_quad_u8 c0(unpack_color(color0, true)); - color_quad_u8 c1(unpack_color(color1, true)); - - pDst[0] = c0; - pDst[1] = c1; - pDst[2].set( (c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U); - pDst[3].set(0, 0, 0, 0); - - return 3; - } - - uint32 dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1) - { - color_quad_u8 c0(unpack_color(color0, true)); - color_quad_u8 c1(unpack_color(color1, true)); - - pDst[0] = c0; - pDst[1] = c1; - - // 12/14/09 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ? - // Turns out some GPU's round and some don't. Great. - //pDst[2].set( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U); - //pDst[3].set( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U); - - pDst[2].set( (c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U); - pDst[3].set( (c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U); - - return 4; - } - - uint32 dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1) - { - if (color0 > color1) - return get_block_colors4(pDst, color0, color1); - else - return get_block_colors3(pDst, color0, color1); - } - - color_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha) - { - CRND_ASSERT(index < 2); - return unpack_color( static_cast((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha ); - } - - uint32 dxt1_block::pack_endpoints(uint32 lo, uint32 hi) - { - CRND_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU)); - return lo | (hi << 16U); - } - - void dxt3_block::set_alpha(uint32 x, uint32 y, uint32 value, bool scaled) - { - CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize)); - - if (scaled) - { - CRND_ASSERT(value <= 0xFF); - value = (value * 15U + 128U) / 255U; - } - else - { - CRND_ASSERT(value <= 0xF); - } - - uint32 ofs = (y << 1U) + (x >> 1U); - uint32 c = m_alpha[ofs]; - - c &= ~(0xF << ((x & 1U) << 2U)); - c |= (value << ((x & 1U) << 2U)); - - m_alpha[ofs] = static_cast(c); - } - - uint32 dxt3_block::get_alpha(uint32 x, uint32 y, bool scaled) const - { - CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize)); - - uint32 value = m_alpha[(y << 1U) + (x >> 1U)]; - if (x & 1) - value >>= 4; - value &= 0xF; - - if (scaled) - value = (value << 4U) | value; - - return value; - } - - uint32 dxt5_block::get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h) - { - pDst[0].a = static_cast(l); - pDst[1].a = static_cast(h); - pDst[2].a = static_cast((l * 4 + h ) / 5); - pDst[3].a = static_cast((l * 3 + h * 2) / 5); - pDst[4].a = static_cast((l * 2 + h * 3) / 5); - pDst[5].a = static_cast((l + h * 4) / 5); - pDst[6].a = 0; - pDst[7].a = 255; - return 6; - } - - uint32 dxt5_block::get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h) - { - pDst[0].a = static_cast(l); - pDst[1].a = static_cast(h); - pDst[2].a = static_cast((l * 6 + h ) / 7); - pDst[3].a = static_cast((l * 5 + h * 2) / 7); - pDst[4].a = static_cast((l * 4 + h * 3) / 7); - pDst[5].a = static_cast((l * 3 + h * 4) / 7); - pDst[6].a = static_cast((l * 2 + h * 5) / 7); - pDst[7].a = static_cast((l + h * 6) / 7); - return 8; - } - - uint32 dxt5_block::get_block_values(color_quad_u8* pDst, uint32 l, uint32 h) - { - if (l > h) - return get_block_values8(pDst, l, h); - else - return get_block_values6(pDst, l, h); - } - - uint32 dxt5_block::get_block_values6(uint32* pDst, uint32 l, uint32 h) - { - pDst[0] = l; - pDst[1] = h; - pDst[2] = (l * 4 + h ) / 5; - pDst[3] = (l * 3 + h * 2) / 5; - pDst[4] = (l * 2 + h * 3) / 5; - pDst[5] = (l + h * 4) / 5; - pDst[6] = 0; - pDst[7] = 255; - return 6; - } - - uint32 dxt5_block::get_block_values8(uint32* pDst, uint32 l, uint32 h) - { - pDst[0] = l; - pDst[1] = h; - pDst[2] = (l * 6 + h ) / 7; - pDst[3] = (l * 5 + h * 2) / 7; - pDst[4] = (l * 4 + h * 3) / 7; - pDst[5] = (l * 3 + h * 4) / 7; - pDst[6] = (l * 2 + h * 5) / 7; - pDst[7] = (l + h * 6) / 7; - return 8; - } - - uint32 dxt5_block::unpack_endpoint(uint32 packed, uint32 index) - { - CRND_ASSERT(index < 2); - return (packed >> (8 * index)) & 0xFF; - } - - uint32 dxt5_block::pack_endpoints(uint32 lo, uint32 hi) - { - CRND_ASSERT((lo <= 0xFF) && (hi <= 0xFF)); - return lo | (hi << 8U); - } - - uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) - { - if (l > h) - return get_block_values8(pDst, l, h); - else - return get_block_values6(pDst, l, h); - } - -} // namespace crnd - -// File: crnd_decode.cpp -#define CRND_CREATE_BYTE_STREAMS 0 - -namespace crnd -{ -#if CRND_CREATE_BYTE_STREAMS - static void write_array_to_file(const char* pFilename, const vector& buf) - { - FILE* pFile = fopen(pFilename, "wb"); - fwrite(&buf[0], buf.size(), 1, pFile); - fclose(pFile); - } -#endif - - struct crnd_chunk_tile_desc - { - // These values are in blocks - uint8 m_x_ofs; - uint8 m_y_ofs; - uint8 m_width; - uint8 m_height; - }; - - struct crnd_chunk_encoding_desc - { - uint32 m_num_tiles; - chunk_tile_desc m_tiles[4]; - }; - -#if 0 - static crnd_chunk_encoding_desc g_crnd_chunk_encodings[cNumChunkEncodings] = - { - { 1, { { 0, 0, 2, 2 } } }, - - { 2, { { 0, 0, 2, 1 }, { 0, 1, 2, 1 } } }, - { 2, { { 0, 0, 1, 2 }, { 1, 0, 1, 2 } } }, - - { 3, { { 0, 0, 2, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } }, - { 3, { { 0, 1, 2, 1 }, { 0, 0, 1, 1 }, { 1, 0, 1, 1 } } }, - - { 3, { { 0, 0, 1, 2 }, { 1, 0, 1, 1 }, { 1, 1, 1, 1 } } }, - { 3, { { 1, 0, 1, 2 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } } }, - - { 1, { { 0, 0, 1, 1 }, { 1, 0, 1, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } } - }; -#endif - - struct crnd_encoding_tile_indices - { - uint8 m_tiles[4]; - }; - - static crnd_encoding_tile_indices g_crnd_chunk_encoding_tiles[cNumChunkEncodings] = - { - { { 0, 0, 0, 0 } }, - - { { 0, 0, 1, 1 } }, - { { 0, 1, 0, 1 } }, - - { { 0, 0, 1, 2 } }, - { { 1, 2, 0, 0 } }, - - { { 0, 1, 0, 2 } }, - { { 1, 0, 2, 0 } }, - - { { 0, 1, 2, 3 } } - }; - - static uint8 g_crnd_chunk_encoding_num_tiles[cNumChunkEncodings] = { 1, 2, 2, 3, 3, 3, 3, 4 }; - - class crn_unpacker - { - public: - inline crn_unpacker() : - m_magic(cMagicValue), - m_pData(NULL), - m_data_size(0), - m_pHeader(NULL) - { - } - - inline ~crn_unpacker() - { - m_magic = 0; - } - - inline bool is_valid() const { return m_magic == cMagicValue; } - - bool init(const void* pData, uint32 data_size) - { - m_pHeader = crnd_get_header(m_tmp_header, pData, data_size); - if (!m_pHeader) - return false; - - m_pData = static_cast(pData); - m_data_size = data_size; - - if (!init_tables()) - return false; - - if (!decode_palettes()) - return false; - - return true; - } - - bool unpack_level( - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) - { - uint32 cur_level_ofs = m_pHeader->m_level_ofs[level_index]; - - uint32 next_level_ofs = m_data_size; - if ((level_index + 1) < (m_pHeader->m_levels)) - next_level_ofs = m_pHeader->m_level_ofs[level_index + 1]; - - CRND_ASSERT(next_level_ofs > cur_level_ofs); - - return unpack_level(m_pData + cur_level_ofs, next_level_ofs - cur_level_ofs, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); - } - - bool unpack_level( - const void* pSrc, uint32 src_size_in_bytes, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) - { - dst_size_in_bytes; - -#ifdef CRND_BUILD_DEBUG - for (uint32 f = 0; f < m_pHeader->m_faces; f++) - if (!pDst[f]) - return false; -#endif - - const uint32 width = math::maximum(m_pHeader->m_width >> level_index, 1U); - const uint32 height = math::maximum(m_pHeader->m_height >> level_index, 1U); - const uint32 blocks_x = (width + 3U) >> 2U; - const uint32 blocks_y = (height + 3U) >> 2U; - const uint32 block_size = ((m_pHeader->m_format == cCRNFmtDXT1) || (m_pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16; - - uint32 minimal_row_pitch = block_size * blocks_x; - if (!row_pitch_in_bytes) - row_pitch_in_bytes = minimal_row_pitch; - else if ((row_pitch_in_bytes < minimal_row_pitch) || (row_pitch_in_bytes & 3)) - return false; - if (dst_size_in_bytes < row_pitch_in_bytes * blocks_y) - return false; - - const uint32 chunks_x = (blocks_x + 1) >> 1; - const uint32 chunks_y = (blocks_y + 1) >> 1; - -#if CRND_CREATE_BYTE_STREAMS - crnd_trace("Index stream: %u bytes\n", src_size_in_bytes); -#endif - - if (!m_codec.start_decoding(static_cast(pSrc), src_size_in_bytes)) - return false; - - bool status = false; - switch (m_pHeader->m_format) - { - case cCRNFmtDXT1: - status = unpack_dxt1((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y); - break; - case cCRNFmtDXT5: - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - case cCRNFmtDXT5_xGxR: - status = unpack_dxt5((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y); - break; - case cCRNFmtDXT5A: - status = unpack_dxt5a((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y); - break; - case cCRNFmtDXN_XY: - case cCRNFmtDXN_YX: - status = unpack_dxn((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y); - break; - default: - return false; - } - if (!status) - return false; - - m_codec.stop_decoding(); - return true; - } - - inline const void* get_data() const { return m_pData; } - inline uint32 get_data_size() const { return m_data_size; } - - private: - enum { cMagicValue = 0x1EF9CABD }; - uint32 m_magic; - - const uint8* m_pData; - uint32 m_data_size; - crn_header m_tmp_header; - const crn_header* m_pHeader; - - symbol_codec m_codec; - - static_huffman_data_model m_chunk_encoding_dm; - static_huffman_data_model m_endpoint_delta_dm[2]; - static_huffman_data_model m_selector_delta_dm[2]; - - crnd::vector m_color_endpoints; - crnd::vector m_color_selectors; - - crnd::vector m_alpha_endpoints; - crnd::vector m_alpha_selectors; - - bool init_tables() - { - if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size)) - return false; - - if (!m_codec.decode_receive_static_data_model(m_chunk_encoding_dm)) - return false; - - if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num)) - return false; - - if (m_pHeader->m_color_endpoints.m_num) - { - if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[0])) return false; - if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[0])) return false; - } - - if (m_pHeader->m_alpha_endpoints.m_num) - { - if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[1])) return false; - if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[1])) return false; - } - - m_codec.stop_decoding(); - - return true; - } - - bool decode_palettes() - { - if (m_pHeader->m_color_endpoints.m_num) - { - if (!decode_color_endpoints()) return false; - if (!decode_color_selectors()) return false; - } - - if (m_pHeader->m_alpha_endpoints.m_num) - { - if (!decode_alpha_endpoints()) return false; - if (!decode_alpha_selectors()) return false; - } - - return true; - } - - bool decode_color_endpoints() - { - const uint32 num_color_endpoints = m_pHeader->m_color_endpoints.m_num; - - if (!m_color_endpoints.resize(num_color_endpoints)) - return false; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_endpoints.m_ofs, m_pHeader->m_color_endpoints.m_size)) - return false; - - static_huffman_data_model dm[2]; - for (uint32 i = 0; i < 2; i++) - if (!m_codec.decode_receive_static_data_model(dm[i])) - return false; - - uint32 a = 0, b = 0, c = 0; - uint32 d = 0, e = 0, f = 0; - - uint32* CRND_RESTRICT pDst = &m_color_endpoints[0]; - - CRND_HUFF_DECODE_BEGIN(m_codec); - -#if CRND_CREATE_BYTE_STREAMS - vector byte_stream; -#endif - - for (uint32 i = 0; i < num_color_endpoints; i++) - { - uint32 da, db, dc, dd, de, df; - CRND_HUFF_DECODE(m_codec, dm[0], da); a = (a + da) & 31; - CRND_HUFF_DECODE(m_codec, dm[1], db); b = (b + db) & 63; - CRND_HUFF_DECODE(m_codec, dm[0], dc); c = (c + dc) & 31; - - CRND_HUFF_DECODE(m_codec, dm[0], dd); d = (d + dd) & 31; - CRND_HUFF_DECODE(m_codec, dm[1], de); e = (e + de) & 63; - CRND_HUFF_DECODE(m_codec, dm[0], df); f = (f + df) & 31; - -#if CRND_CREATE_BYTE_STREAMS - byte_stream.push_back(da); - byte_stream.push_back(db); - byte_stream.push_back(dc); - byte_stream.push_back(dd); - byte_stream.push_back(de); - byte_stream.push_back(df); -#endif - - if (c_crnd_little_endian_platform) - *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U); - else - *pDst++ = f | (e << 5U) | (d << 11U) | (c << 16U) | (b << 21U) | (a << 27U); - } - - CRND_HUFF_DECODE_END(m_codec); - - m_codec.stop_decoding(); - -#if CRND_CREATE_BYTE_STREAMS - write_array_to_file(L"colorendpoints.bin", byte_stream); - crnd_trace("color endpoints: %u\n", (uint)m_pHeader->m_color_endpoints.m_size); -#endif - - return true; - } - - bool decode_color_selectors() - { - const uint32 cMaxSelectorValue = 3U; - const uint32 cMaxUniqueSelectorDeltas = cMaxSelectorValue * 2U + 1U; - - const uint32 num_color_selectors = m_pHeader->m_color_selectors.m_num; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_selectors.m_ofs, m_pHeader->m_color_selectors.m_size)) - return false; - - static_huffman_data_model dm; - if (!m_codec.decode_receive_static_data_model(dm)) - return false; - - int32 delta0[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas]; - int32 delta1[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas]; - int32 l = -(int32)cMaxSelectorValue, m = -(int32)cMaxSelectorValue; - for (uint32 i = 0; i < (cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas); i++) - { - delta0[i] = l; - delta1[i] = m; - - if (++l > (int32)cMaxSelectorValue) - { - l = -(int32)cMaxSelectorValue; - m++; - } - } - - uint32 cur[16]; - utils::zero_object(cur); - - if (!m_color_selectors.resize(num_color_selectors)) - return false; - - uint32* CRND_RESTRICT pDst = &m_color_selectors[0]; - - const uint8* pFrom_linear = g_dxt1_from_linear; - - CRND_HUFF_DECODE_BEGIN(m_codec); - -#if CRND_CREATE_BYTE_STREAMS - vector byte_stream; -#endif - - for (uint32 i = 0; i < num_color_selectors; i++) - { - for (uint32 j = 0; j < 8; j++) - { - int32 sym; - CRND_HUFF_DECODE(m_codec, dm, sym); - -#if CRND_CREATE_BYTE_STREAMS - byte_stream.push_back(sym); -#endif - - cur[j*2+0] = (delta0[sym] + cur[j*2+0]) & 3; - cur[j*2+1] = (delta1[sym] + cur[j*2+1]) & 3; - } - - if (c_crnd_little_endian_platform) - { - *pDst++ = - (pFrom_linear[cur[0 ]] ) | (pFrom_linear[cur[1 ]] << 2) | (pFrom_linear[cur[2 ]] << 4) | (pFrom_linear[cur[3 ]] << 6) | - (pFrom_linear[cur[4 ]] << 8) | (pFrom_linear[cur[5 ]] << 10) | (pFrom_linear[cur[6 ]] << 12) | (pFrom_linear[cur[7 ]] << 14) | - (pFrom_linear[cur[8 ]] << 16) | (pFrom_linear[cur[9 ]] << 18) | (pFrom_linear[cur[10]] << 20) | (pFrom_linear[cur[11]] << 22) | - (pFrom_linear[cur[12]] << 24) | (pFrom_linear[cur[13]] << 26) | (pFrom_linear[cur[14]] << 28) | (pFrom_linear[cur[15]] << 30); - } - else - { - *pDst++ = - (pFrom_linear[cur[8 ]] ) | (pFrom_linear[cur[9 ]] << 2) | (pFrom_linear[cur[10]] << 4) | (pFrom_linear[cur[11]] << 6) | - (pFrom_linear[cur[12]] << 8) | (pFrom_linear[cur[13]] << 10) | (pFrom_linear[cur[14]] << 12) | (pFrom_linear[cur[15]] << 14) | - (pFrom_linear[cur[0 ]] << 16) | (pFrom_linear[cur[1 ]] << 18) | (pFrom_linear[cur[2 ]] << 20) | (pFrom_linear[cur[3 ]] << 22) | - (pFrom_linear[cur[4 ]] << 24) | (pFrom_linear[cur[5 ]] << 26) | (pFrom_linear[cur[6 ]] << 28) | (pFrom_linear[cur[7 ]] << 30); - } - } - - CRND_HUFF_DECODE_END(m_codec); - - m_codec.stop_decoding(); - -#if CRND_CREATE_BYTE_STREAMS - write_array_to_file(L"colorselectors.bin", byte_stream); - crnd_trace("color selectors: %u\n", (uint)m_pHeader->m_color_selectors.m_size); -#endif - - return true; - } - - bool decode_alpha_endpoints() - { - const uint32 num_alpha_endpoints = m_pHeader->m_alpha_endpoints.m_num; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_endpoints.m_ofs, m_pHeader->m_alpha_endpoints.m_size)) - return false; - - static_huffman_data_model dm; - if (!m_codec.decode_receive_static_data_model(dm)) - return false; - - if (!m_alpha_endpoints.resize(num_alpha_endpoints)) - return false; - - uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0]; - uint32 a = 0, b = 0; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 i = 0; i < num_alpha_endpoints; i++) - { - uint sa; CRND_HUFF_DECODE(m_codec, dm, sa); - uint sb; CRND_HUFF_DECODE(m_codec, dm, sb); - - a = (sa + a) & 255; - b = (sb + b) & 255; - - *pDst++ = (uint16)(a | (b << 8)); - } - - CRND_HUFF_DECODE_END(m_codec); - - m_codec.stop_decoding(); - - return true; - } - - bool decode_alpha_selectors() - { - const uint32 cMaxSelectorValue = 7U; - const uint32 cMaxUniqueSelectorDeltas = cMaxSelectorValue * 2U + 1U; - - const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size)) - return false; - - static_huffman_data_model dm; - if (!m_codec.decode_receive_static_data_model(dm)) - return false; - - int32 delta0[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas]; - int32 delta1[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas]; - int32 l = -(int32)cMaxSelectorValue, m = -(int32)cMaxSelectorValue; - for (uint32 i = 0; i < (cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas); i++) - { - delta0[i] = l; - delta1[i] = m; - - if (++l > (int32)cMaxSelectorValue) - { - l = -(int32)cMaxSelectorValue; - m++; - } - } - - uint32 cur[16]; - utils::zero_object(cur); - - if (!m_alpha_selectors.resize(num_alpha_selectors * 3)) - return false; - - uint16* CRND_RESTRICT pDst = &m_alpha_selectors[0]; - - const uint8* pFrom_linear = g_dxt5_from_linear; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 i = 0; i < num_alpha_selectors; i++) - { - for (uint32 j = 0; j < 8; j++) - { - int32 sym; - CRND_HUFF_DECODE(m_codec, dm, sym); - - cur[j*2+0] = (delta0[sym] + cur[j*2+0]) & 7; - cur[j*2+1] = (delta1[sym] + cur[j*2+1]) & 7; - //cur[j*2+0] = ((sym%15)-7 + cur[j*2+0]) & 7; - //cur[j*2+1] = ((sym/15)-7 + cur[j*2+1]) & 7; - } - -#if 0 - dxt5_block blk; - for (uint32 y = 0; y < 4; y++) - for (uint32 x = 0; x < 4; x++) - blk.set_selector(x, y, pFrom_linear[cur[x+y*4]]); - - *pDst++ = blk.get_selectors_as_word(0); - *pDst++ = blk.get_selectors_as_word(1); - *pDst++ = blk.get_selectors_as_word(2); -#else - *pDst++ = (uint16)((pFrom_linear[cur[0 ]] ) | (pFrom_linear[cur[1 ]] << 3) | (pFrom_linear[cur[2 ]] << 6) | (pFrom_linear[cur[3 ]] << 9) | - (pFrom_linear[cur[4 ]] << 12) | (pFrom_linear[cur[5 ]] << 15)); - - *pDst++ = (uint16)((pFrom_linear[cur[5 ]] >> 1) | (pFrom_linear[cur[6 ]] << 2) | (pFrom_linear[cur[7 ]] << 5) | - (pFrom_linear[cur[8 ]] << 8) | (pFrom_linear[cur[9 ]] << 11) | (pFrom_linear[cur[10]] << 14)); - - *pDst++ = (uint16)((pFrom_linear[cur[10]] >> 2) | (pFrom_linear[cur[11]] << 1) | (pFrom_linear[cur[12]] << 4) | - (pFrom_linear[cur[13]] << 7) | (pFrom_linear[cur[14]] << 10) | (pFrom_linear[cur[15]] << 13)); -#endif - } - - CRND_HUFF_DECODE_END(m_codec); - - m_codec.stop_decoding(); - - return true; - } - - static inline uint32 tiled_offset_2d_outer(uint32 y, uint32 AlignedWidth, uint32 LogBpp) - { - uint32 Macro = ((y >> 5) * (AlignedWidth >> 5)) << (LogBpp + 7); - uint32 Micro = ((y & 6) << 2) << LogBpp; - - return Macro + - ((Micro & ~15) << 1) + - (Micro & 15) + - ((y & 8) << (3 + LogBpp)) + ((y & 1) << 4); - } - - static inline uint32 tiled_offset_2d_inner(uint32 x, uint32 y, uint32 LogBpp, uint32 BaseOffset) - { - uint32 Macro = (x >> 5) << (LogBpp + 7); - uint32 Micro = (x & 7) << LogBpp; - uint32 Offset = BaseOffset + Macro + ((Micro & ~15) << 1) + (Micro & 15); - - return ((Offset & ~511) << 3) + ((Offset & 448) << 2) + (Offset & 63) + - ((y & 16) << 7) + - (((((y & 8) >> 2) + (x >> 3)) & 3) << 6); - } - - static inline void limit(uint& x, uint n) - { - int v = x - n; - int msk = (v >> 31); - x = (x & msk) | (v & ~msk); - } - - bool unpack_dxt1(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) - { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 num_color_selectors = m_color_selectors.size(); - - uint32 prev_color_endpoint_index = 0; - uint32 prev_color_selector_index = 0; - - const uint32 num_faces = m_pHeader->m_faces; - - const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 8; - - CRND_HUFF_DECODE_BEGIN(m_codec); - -#if CRND_CREATE_BYTE_STREAMS - vector tile_encoding_stream; - vector endpoint_indices_stream; - vector selector_indices_stream; -#endif - - for (uint32 f = 0; f < num_faces; f++) - { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) - { - int32 start_x = 0; - int32 end_x = chunks_x; - int32 dir_x = 1; - int32 block_delta = cBytesPerBlock*2; - uint8* CRND_RESTRICT pBlock = pRow; - - if (y & 1) - { - start_x = chunks_x - 1; - end_x = -1; - dir_x = -1; - block_delta = -cBytesPerBlock*2; - pBlock += (chunks_x - 1) * cBytesPerBlock * 2; - } - - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (int32 x = start_x; x != end_x; x += dir_x) - { - uint32 color_endpoints[4]; - - if (chunk_encoding_bits == 1) - { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); -#if CRND_CREATE_BYTE_STREAMS - tile_encoding_stream.push_back(chunk_encoding_bits & 7); - tile_encoding_stream.push_back((chunk_encoding_bits >> 3) & 7); - tile_encoding_stream.push_back((chunk_encoding_bits >> 6) & 7); -#endif - chunk_encoding_bits |= 512; - } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index]; - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta); -#if CRND_CREATE_BYTE_STREAMS - endpoint_indices_stream.push_back(delta); -#endif - prev_color_endpoint_index += delta; - limit(prev_color_endpoint_index, num_color_endpoints); - color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index]; - } - - const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - if ((!skip_bottom_row) && (!skip_right_col)) - { - //CRND_ASSERT( ((uint8*)&pD[4 + row_pitch_in_dwords] - pDst) <= dst_size_in_bytes ); - - pD[0] = color_endpoints[pTile_indices[0]]; - CRND_WRITE_BARRIER - uint32 delta0; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta0); -#if CRND_CREATE_BYTE_STREAMS - selector_indices_stream.push_back(delta0); -#endif - prev_color_selector_index += delta0; - limit(prev_color_selector_index, num_color_selectors); - pD[1] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER - - pD[2] = color_endpoints[pTile_indices[1]]; - CRND_WRITE_BARRIER - uint32 delta1; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta1); -#if CRND_CREATE_BYTE_STREAMS - selector_indices_stream.push_back(delta1); -#endif - prev_color_selector_index += delta1; - limit(prev_color_selector_index, num_color_selectors); - pD[3] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER - - pD[0 + row_pitch_in_dwords] = color_endpoints[pTile_indices[2]]; - CRND_WRITE_BARRIER - uint32 delta2; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta2); -#if CRND_CREATE_BYTE_STREAMS - selector_indices_stream.push_back(delta2); -#endif - prev_color_selector_index += delta2; - limit(prev_color_selector_index, num_color_selectors); - pD[1 + row_pitch_in_dwords] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER - - pD[2 + row_pitch_in_dwords] = color_endpoints[pTile_indices[3]]; - CRND_WRITE_BARRIER - uint32 delta3; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta3); -#if CRND_CREATE_BYTE_STREAMS - selector_indices_stream.push_back(delta3); -#endif - prev_color_selector_index += delta3; - limit(prev_color_selector_index, num_color_selectors); - pD[3 + row_pitch_in_dwords] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER - } - else - { - for (uint32 by = 0; by < 2; by++) - { - pD = (uint32*)((uint8*)pBlock + row_pitch_in_bytes * by); - for (uint32 bx = 0; bx < 2; bx++, pD += 2) - { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta); -#if CRND_CREATE_BYTE_STREAMS - selector_indices_stream.push_back(delta); -#endif - prev_color_selector_index += delta; - limit(prev_color_selector_index, num_color_selectors); - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) - { - pD[0] = color_endpoints[pTile_indices[bx + by * 2]]; - CRND_WRITE_BARRIER - pD[1] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER - } - } - } - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - -#if CRND_CREATE_BYTE_STREAMS - write_array_to_file(L"tile_encodings.bin", tile_encoding_stream); - write_array_to_file(L"endpoint_indices.bin", endpoint_indices_stream); - write_array_to_file(L"selector_indices.bin", selector_indices_stream); -#endif - - return true; - } - - bool unpack_dxt5(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) - { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 num_color_selectors = m_color_selectors.size(); - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; - - uint32 prev_color_endpoint_index = 0; - uint32 prev_color_selector_index = 0; - uint32 prev_alpha_endpoint_index = 0; - uint32 prev_alpha_selector_index = 0; - - const uint32 num_faces = m_pHeader->m_faces; - - //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 16; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) - { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) - { - int32 start_x = 0; - int32 end_x = chunks_x; - int32 dir_x = 1; - int32 block_delta = cBytesPerBlock*2; - uint8* CRND_RESTRICT pBlock = pRow; - - if (y & 1) - { - start_x = chunks_x - 1; - end_x = -1; - dir_x = -1; - block_delta = -cBytesPerBlock*2; - pBlock += (chunks_x - 1) * cBytesPerBlock * 2; - } - - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (int32 x = start_x; x != end_x; x += dir_x) - { - uint32 color_endpoints[4]; - uint32 alpha_endpoints[4]; - - if (chunk_encoding_bits == 1) - { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; - } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index]; - - const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - prev_alpha_endpoint_index += delta; - limit(prev_alpha_endpoint_index, num_alpha_endpoints); - alpha_endpoints[i] = m_alpha_endpoints[prev_alpha_endpoint_index]; - } - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta); - prev_color_endpoint_index += delta; - limit(prev_color_endpoint_index, num_color_endpoints); - color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index]; - } - - pD = (uint32*)pBlock; - for (uint32 by = 0; by < 2; by++) - { - for (uint32 bx = 0; bx < 2; bx++, pD += 4) - { - uint32 delta0; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0); - prev_alpha_selector_index += delta0; - limit(prev_alpha_selector_index, num_alpha_selectors); - - uint32 delta1; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta1); - prev_color_selector_index += delta1; - limit(prev_color_selector_index, num_color_selectors); - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) - { - const uint32 tile_index = pTile_indices[bx + by * 2]; - const uint16* pAlpha_selectors = &m_alpha_selectors[prev_alpha_selector_index * 3]; - -#ifdef CRND_BIG_ENDIAN_PLATFORM - pD[0] = (alpha_endpoints[tile_index] << 16) | pAlpha_selectors[0]; - CRND_WRITE_BARRIER - pD[1] = (pAlpha_selectors[1] << 16) | pAlpha_selectors[2]; - CRND_WRITE_BARRIER - pD[2] = color_endpoints[tile_index]; - CRND_WRITE_BARRIER - pD[3] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER -#else - pD[0] = alpha_endpoints[tile_index] | (pAlpha_selectors[0] << 16); - CRND_WRITE_BARRIER - pD[1] = pAlpha_selectors[1] | (pAlpha_selectors[2] << 16); - CRND_WRITE_BARRIER - pD[2] = color_endpoints[tile_index]; - CRND_WRITE_BARRIER - pD[3] = m_color_selectors[prev_color_selector_index]; - CRND_WRITE_BARRIER -#endif - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - - return true; - } - - bool unpack_dxn(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) - { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; - - uint32 prev_alpha0_endpoint_index = 0; - uint32 prev_alpha0_selector_index = 0; - uint32 prev_alpha1_endpoint_index = 0; - uint32 prev_alpha1_selector_index = 0; - - const uint32 num_faces = m_pHeader->m_faces; - - //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 16; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) - { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) - { - int32 start_x = 0; - int32 end_x = chunks_x; - int32 dir_x = 1; - int32 block_delta = cBytesPerBlock*2; - uint8* CRND_RESTRICT pBlock = pRow; - - if (y & 1) - { - start_x = chunks_x - 1; - end_x = -1; - dir_x = -1; - block_delta = -cBytesPerBlock*2; - pBlock += (chunks_x - 1) * cBytesPerBlock * 2; - } - - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (int32 x = start_x; x != end_x; x += dir_x) - { - uint32 alpha0_endpoints[4]; - uint32 alpha1_endpoints[4]; - - if (chunk_encoding_bits == 1) - { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; - } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index]; - - const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - prev_alpha0_endpoint_index += delta; - limit(prev_alpha0_endpoint_index, num_alpha_endpoints); - alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index]; - } - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - prev_alpha1_endpoint_index += delta; - limit(prev_alpha1_endpoint_index, num_alpha_endpoints); - alpha1_endpoints[i] = m_alpha_endpoints[prev_alpha1_endpoint_index]; - } - - pD = (uint32*)pBlock; - for (uint32 by = 0; by < 2; by++) - { - for (uint32 bx = 0; bx < 2; bx++, pD += 4) - { - uint32 delta0; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0); - prev_alpha0_selector_index += delta0; - limit(prev_alpha0_selector_index, num_alpha_selectors); - - uint32 delta1; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta1); - prev_alpha1_selector_index += delta1; - limit(prev_alpha1_selector_index, num_alpha_selectors); - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) - { - const uint32 tile_index = pTile_indices[bx + by * 2]; - const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3]; - const uint16* pAlpha1_selectors = &m_alpha_selectors[prev_alpha1_selector_index * 3]; - -#ifdef CRND_BIG_ENDIAN_PLATFORM - pD[0] = (alpha0_endpoints[tile_index] << 16) | pAlpha0_selectors[0]; - CRND_WRITE_BARRIER - pD[1] = (pAlpha0_selectors[1] << 16) | pAlpha0_selectors[2]; - CRND_WRITE_BARRIER - pD[2] = (alpha1_endpoints[tile_index] << 16) | pAlpha1_selectors[0]; - CRND_WRITE_BARRIER - pD[3] = (pAlpha1_selectors[1] << 16) | pAlpha1_selectors[2]; - CRND_WRITE_BARRIER -#else - pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16); - CRND_WRITE_BARRIER - pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - CRND_WRITE_BARRIER - pD[2] = alpha1_endpoints[tile_index] | (pAlpha1_selectors[0] << 16); - CRND_WRITE_BARRIER - pD[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16); - CRND_WRITE_BARRIER -#endif - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - - return true; - } - - bool unpack_dxt5a(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) - { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; - - uint32 prev_alpha0_endpoint_index = 0; - uint32 prev_alpha0_selector_index = 0; - - const uint32 num_faces = m_pHeader->m_faces; - - const int32 cBytesPerBlock = 8; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) - { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) - { - int32 start_x = 0; - int32 end_x = chunks_x; - int32 dir_x = 1; - int32 block_delta = cBytesPerBlock*2; - uint8* CRND_RESTRICT pBlock = pRow; - - if (y & 1) - { - start_x = chunks_x - 1; - end_x = -1; - dir_x = -1; - block_delta = -cBytesPerBlock*2; - pBlock += (chunks_x - 1) * cBytesPerBlock * 2; - } - - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (int32 x = start_x; x != end_x; x += dir_x) - { - uint32 alpha0_endpoints[4]; - - if (chunk_encoding_bits == 1) - { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; - } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index]; - - const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 i = 0; i < num_tiles; i++) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - prev_alpha0_endpoint_index += delta; - limit(prev_alpha0_endpoint_index, num_alpha_endpoints); - alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index]; - } - - pD = (uint32*)pBlock; - for (uint32 by = 0; by < 2; by++) - { - for (uint32 bx = 0; bx < 2; bx++, pD += 2) - { - uint32 delta; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta); - prev_alpha0_selector_index += delta; - limit(prev_alpha0_selector_index, num_alpha_selectors); - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) - { - const uint32 tile_index = pTile_indices[bx + by * 2]; - const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3]; - -#if CRND_BIG_ENDIAN_PLATFORM - pD[0] = (alpha0_endpoints[tile_index] << 16) | pAlpha0_selectors[0]; - CRND_WRITE_BARRIER - pD[1] = (pAlpha0_selectors[1] << 16) | pAlpha0_selectors[2]; - CRND_WRITE_BARRIER -#else - pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16); - CRND_WRITE_BARRIER - pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - CRND_WRITE_BARRIER -#endif - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - - return true; - } - }; - - crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size) - { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return NULL; - - crn_unpacker* p = crnd_new(); - if (!p) - return NULL; - - if (!p->init(pData, data_size)) - { - crnd_delete(p); - return NULL; - } - - return p; - } - - bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size) - { - if (!pContext) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - if (ppData) - *ppData = pUnpacker->get_data(); - - if (pData_size) - *pData_size = pUnpacker->get_data_size(); - - return true; - } - - bool crnd_unpack_level( - crnd_unpack_context pContext, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) - { - if ((!pContext) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels)) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - return pUnpacker->unpack_level(pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); - } - - bool crnd_unpack_level_segmented( - crnd_unpack_context pContext, - const void* pSrc, uint32 src_size_in_bytes, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) - { - if ((!pContext) || (!pSrc) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels)) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - return pUnpacker->unpack_level(pSrc, src_size_in_bytes, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); - } - - bool crnd_unpack_end(crnd_unpack_context pContext) - { - if (!pContext) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - crnd_delete(pUnpacker); - - return true; - } - -} // namespace crnd - -#endif // CRND_HEADER_FILE_ONLY - - //------------------------------------------------------------------------------ - // - // crunch/crnlib uses a modified ZLIB license. Specifically, it's the same as zlib except that - // public credits for using the library are *required*. - // - // Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved. - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. - // - // 2. If you use this software in a product, this acknowledgment in the product - // documentation or credits is required: - // - // "Crunch Library Copyright (c) 2010-2016 Richard Geldreich, Jr." - // - // 3. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // - // 4. This notice may not be removed or altered from any source distribution. - // - //------------------------------------------------------------------------------ - diff --git a/Texture2DDecoderNative/crunch/crnlib.h b/Texture2DDecoderNative/crunch/crnlib.h deleted file mode 100644 index 40b69b4..0000000 --- a/Texture2DDecoderNative/crunch/crnlib.h +++ /dev/null @@ -1,645 +0,0 @@ -// File: crnlib.h - Advanced DXTn texture compression library. -// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved. -// See copyright notice and license at the end of this file. -// -// This header file contains the public crnlib declarations for DXTn, -// clustered DXTn, and CRN compression/decompression. -// -// Note: This library does NOT need to be linked into your game executable if -// all you want to do is transcode .CRN files to raw DXTn bits at run-time. -// The crn_decomp.h header file library contains all the code necessary for -// decompression. -// -// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing -#ifndef CRNLIB_H -#define CRNLIB_H - -#ifdef _MSC_VER -#pragma warning (disable: 4127) // conditional expression is constant -#endif - -#define CRNLIB_VERSION 104 - -#define CRNLIB_SUPPORT_ATI_COMPRESS 0 -#define CRNLIB_SUPPORT_SQUISH 0 - -typedef unsigned char crn_uint8; -typedef unsigned short crn_uint16; -typedef unsigned int crn_uint32; -typedef signed char crn_int8; -typedef signed short crn_int16; -typedef signed int crn_int32; -typedef unsigned int crn_bool; - -// crnlib can compress to these file types. -enum crn_file_type -{ - // .CRN - cCRNFileTypeCRN = 0, - - // .DDS using regular DXT or clustered DXT - cCRNFileTypeDDS, - - cCRNFileTypeForceDWORD = 0xFFFFFFFF -}; - -// Supported compressed pixel formats. -// Basically all the standard DX9 formats, with some swizzled DXT5 formats -// (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats. -enum crn_format -{ - cCRNFmtInvalid = -1, - - cCRNFmtDXT1 = 0, - - cCRNFmtFirstValid = cCRNFmtDXT1, - - // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS. - cCRNFmtDXT3, - - cCRNFmtDXT5, - - // Various DXT5 derivatives - cCRNFmtDXT5_CCxY, // Luma-chroma - cCRNFmtDXT5_xGxR, // Swizzled 2-component - cCRNFmtDXT5_xGBR, // Swizzled 3-component - cCRNFmtDXT5_AGBR, // Swizzled 4-component - - // ATI 3DC and X360 DXN - cCRNFmtDXN_XY, - cCRNFmtDXN_YX, - - // DXT5 alpha blocks only - cCRNFmtDXT5A, - - cCRNFmtETC1, - - cCRNFmtTotal, - - cCRNFmtForceDWORD = 0xFFFFFFFF -}; - -// Various library/file format limits. -enum crn_limits -{ - // Max. mipmap level resolution on any axis. - cCRNMaxLevelResolution = 4096, - - cCRNMinPaletteSize = 8, - cCRNMaxPaletteSize = 8192, - - cCRNMaxFaces = 6, - cCRNMaxLevels = 16, - - cCRNMaxHelperThreads = 16, - - cCRNMinQualityLevel = 0, - cCRNMaxQualityLevel = 255 -}; - -// CRN/DDS compression flags. -// See the m_flags member in the crn_comp_params struct, below. -enum crn_comp_flags -{ - // Enables perceptual colorspace distance metrics if set. - // Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps! - // Default: Set - cCRNCompFlagPerceptual = 1, - - // Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed. - // Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine - // where large macroblocks can be used without artifacts isn't perfect. - // Default: Set. - cCRNCompFlagHierarchical = 2, - - // cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews. - // Default: Not set. - cCRNCompFlagQuick = 4, - - // DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency. - // DXT5: OK to use both DXT5 block types. - // Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types. - // Default: Set. - cCRNCompFlagUseBothBlockTypes = 8, - - // OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha). - // Currently only used when writing to .DDS files, .CRN never uses alpha blocks. - // Default: Not set. - cCRNCompFlagUseTransparentIndicesForBlack = 16, - - // Disables endpoint caching, for more deterministic output. - // Currently only used when writing to .DDS files. - // Default: Not set. - cCRNCompFlagDisableEndpointCaching = 32, - - // If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files. - // Default: Not set. - cCRNCompFlagManualPaletteSizes = 64, - - // If enabled, DXT1A alpha blocks are used to encode single bit transparency. - // Default: Not set. - cCRNCompFlagDXT1AForTransparency = 128, - - // If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr). - // This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks - // with some chroma present if doing so will ultimately lead to lower luma error). - // Only enable on grayscale source images. - // Default: Not set. - cCRNCompFlagGrayscaleSampling = 256, - - // If enabled, debug information will be output during compression. - // Default: Not set. - cCRNCompFlagDebugging = 0x80000000, - - cCRNCompFlagForceDWORD = 0xFFFFFFFF -}; - -// Controls DXTn quality vs. speed control - only used when compressing to .DDS. -enum crn_dxt_quality -{ - cCRNDXTQualitySuperFast, - cCRNDXTQualityFast, - cCRNDXTQualityNormal, - cCRNDXTQualityBetter, - cCRNDXTQualityUber, - - cCRNDXTQualityTotal, - - cCRNDXTQualityForceDWORD = 0xFFFFFFFF -}; - -// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS. -enum crn_dxt_compressor_type -{ - cCRNDXTCompressorCRN, // Use crnlib's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and crnlib's ETC1 is a lot fasterw with similiar quality to Erricson's) - cCRNDXTCompressorCRNF, // Use crnlib's "fast" DXTc block compressor - cCRNDXTCompressorRYG, // Use RYG's DXTc block compressor (low quality, but very fast) - -#if CRNLIB_SUPPORT_ATI_COMPRESS - cCRNDXTCompressorATI, -#endif - -#if CRNLIB_SUPPORT_SQUISH - cCRNDXTCompressorSquish, -#endif - - cCRNTotalDXTCompressors, - - cCRNDXTCompressorForceDWORD = 0xFFFFFFFF -}; - -// Progress callback function. -// Processing will stop prematurely (and fail) if the callback returns false. -// phase_index, total_phases - high level progress -// subphase_index, total_subphases - progress within current phase -typedef crn_bool (*crn_progress_callback_func)(crn_uint32 phase_index, crn_uint32 total_phases, crn_uint32 subphase_index, crn_uint32 total_subphases, void* pUser_data_ptr); - -// CRN/DDS compression parameters struct. -struct crn_comp_params -{ - inline crn_comp_params() { clear(); } - - // Clear struct to default parameters. - inline void clear() - { - m_size_of_obj = sizeof(*this); - m_file_type = cCRNFileTypeCRN; - m_faces = 1; - m_width = 0; - m_height = 0; - m_levels = 1; - m_format = cCRNFmtDXT1; - m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes; - - for (crn_uint32 f = 0; f < cCRNMaxFaces; f++) - for (crn_uint32 l = 0; l < cCRNMaxLevels; l++) - m_pImages[f][l] = NULL; - - m_target_bitrate = 0.0f; - m_quality_level = cCRNMaxQualityLevel; - m_dxt1a_alpha_threshold = 128; - m_dxt_quality = cCRNDXTQualityUber; - m_dxt_compressor_type = cCRNDXTCompressorCRN; - m_alpha_component = 3; - - m_crn_adaptive_tile_color_psnr_derating = 2.0f; - m_crn_adaptive_tile_alpha_psnr_derating = 2.0f; - m_crn_color_endpoint_palette_size = 0; - m_crn_color_selector_palette_size = 0; - m_crn_alpha_endpoint_palette_size = 0; - m_crn_alpha_selector_palette_size = 0; - - m_num_helper_threads = 0; - m_userdata0 = 0; - m_userdata1 = 0; - m_pProgress_func = NULL; - m_pProgress_func_data = NULL; - } - - inline bool operator== (const crn_comp_params& rhs) const - { -#define CRNLIB_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0) - CRNLIB_COMP(m_size_of_obj); - CRNLIB_COMP(m_file_type); - CRNLIB_COMP(m_faces); - CRNLIB_COMP(m_width); - CRNLIB_COMP(m_height); - CRNLIB_COMP(m_levels); - CRNLIB_COMP(m_format); - CRNLIB_COMP(m_flags); - CRNLIB_COMP(m_target_bitrate); - CRNLIB_COMP(m_quality_level); - CRNLIB_COMP(m_dxt1a_alpha_threshold); - CRNLIB_COMP(m_dxt_quality); - CRNLIB_COMP(m_dxt_compressor_type); - CRNLIB_COMP(m_alpha_component); - CRNLIB_COMP(m_crn_adaptive_tile_color_psnr_derating); - CRNLIB_COMP(m_crn_adaptive_tile_alpha_psnr_derating); - CRNLIB_COMP(m_crn_color_endpoint_palette_size); - CRNLIB_COMP(m_crn_color_selector_palette_size); - CRNLIB_COMP(m_crn_alpha_endpoint_palette_size); - CRNLIB_COMP(m_crn_alpha_selector_palette_size); - CRNLIB_COMP(m_num_helper_threads); - CRNLIB_COMP(m_userdata0); - CRNLIB_COMP(m_userdata1); - CRNLIB_COMP(m_pProgress_func); - CRNLIB_COMP(m_pProgress_func_data); - - for (crn_uint32 f = 0; f < cCRNMaxFaces; f++) - for (crn_uint32 l = 0; l < cCRNMaxLevels; l++) - CRNLIB_COMP(m_pImages[f][l]); - -#undef CRNLIB_COMP - return true; - } - - // Returns true if the input parameters are reasonable. - inline bool check() const - { - if ( (m_file_type > cCRNFileTypeDDS) || - (((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) || - (m_dxt1a_alpha_threshold > 255) || - ((m_faces != 1) && (m_faces != 6)) || - ((m_width < 1) || (m_width > cCRNMaxLevelResolution)) || - ((m_height < 1) || (m_height > cCRNMaxLevelResolution)) || - ((m_levels < 1) || (m_levels > cCRNMaxLevels)) || - ((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) || - ((m_crn_color_endpoint_palette_size) && ((m_crn_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_color_endpoint_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_color_selector_palette_size) && ((m_crn_color_selector_palette_size < cCRNMinPaletteSize) || (m_crn_color_selector_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_alpha_endpoint_palette_size) && ((m_crn_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_alpha_selector_palette_size) && ((m_crn_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_selector_palette_size > cCRNMaxPaletteSize))) || - (m_alpha_component > 3) || - (m_num_helper_threads > cCRNMaxHelperThreads) || - (m_dxt_quality > cCRNDXTQualityUber) || - (m_dxt_compressor_type >= cCRNTotalDXTCompressors) ) - { - return false; - } - return true; - } - - // Helper to set/get flags from m_flags member. - inline bool get_flag(crn_comp_flags flag) const { return (m_flags & flag) != 0; } - inline void set_flag(crn_comp_flags flag, bool val) { m_flags &= ~flag; if (val) m_flags |= flag; } - - crn_uint32 m_size_of_obj; - - crn_file_type m_file_type; // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS. - - crn_uint32 m_faces; // 1 (2D map) or 6 (cubemap) - crn_uint32 m_width; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - crn_uint32 m_height; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - crn_uint32 m_levels; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - - crn_format m_format; // Output pixel format. - - crn_uint32 m_flags; // see crn_comp_flags enum - - // Array of pointers to 32bpp input images. - const crn_uint32* m_pImages[cCRNMaxFaces][cCRNMaxLevels]; - - // Target bitrate - if non-zero, the compressor will use an interpolative search to find the - // highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll - // try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow. - float m_target_bitrate; - - // Desired quality level. - // Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint. - crn_uint32 m_quality_level; // [cCRNMinQualityLevel, cCRNMaxQualityLevel] - - // DXTn compression parameters. - crn_uint32 m_dxt1a_alpha_threshold; - crn_dxt_quality m_dxt_quality; - crn_dxt_compressor_type m_dxt_compressor_type; - - // Alpha channel's component. Defaults to 3. - crn_uint32 m_alpha_component; - - // Various low-level CRN specific parameters. - float m_crn_adaptive_tile_color_psnr_derating; - float m_crn_adaptive_tile_alpha_psnr_derating; - - crn_uint32 m_crn_color_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - crn_uint32 m_crn_color_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - - crn_uint32 m_crn_alpha_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - crn_uint32 m_crn_alpha_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - - // Number of helper threads to create during compression. 0=no threading. - crn_uint32 m_num_helper_threads; - - // CRN userdata0 and userdata1 members, which are written directly to the header of the output file. - crn_uint32 m_userdata0; - crn_uint32 m_userdata1; - - // User provided progress callback. - crn_progress_callback_func m_pProgress_func; - void* m_pProgress_func_data; -}; - -// Mipmap generator's mode. -enum crn_mip_mode -{ - cCRNMipModeUseSourceOrGenerateMips, // Use source texture's mipmaps if it has any, otherwise generate new mipmaps - cCRNMipModeUseSourceMips, // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps - cCRNMipModeGenerateMips, // Always generate new mipmaps - cCRNMipModeNoMips, // Output texture has no mipmaps - - cCRNMipModeTotal, - - cCRNModeForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_mip_mode_desc(crn_mip_mode m); -const char* crn_get_mip_mode_name(crn_mip_mode m); - -// Mipmap generator's filter kernel. -enum crn_mip_filter -{ - cCRNMipFilterBox, - cCRNMipFilterTent, - cCRNMipFilterLanczos4, - cCRNMipFilterMitchell, - cCRNMipFilterKaiser, // Kaiser=default mipmap filter - - cCRNMipFilterTotal, - - cCRNMipFilterForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_mip_filter_name(crn_mip_filter f); - -// Mipmap generator's scale mode. -enum crn_scale_mode -{ - cCRNSMDisabled, - cCRNSMAbsolute, - cCRNSMRelative, - cCRNSMLowerPow2, - cCRNSMNearestPow2, - cCRNSMNextPow2, - - cCRNSMTotal, - - cCRNSMForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_scale_mode_desc(crn_scale_mode sm); - -// Mipmap generator parameters. -struct crn_mipmap_params -{ - inline crn_mipmap_params() { clear(); } - - inline void clear() - { - m_size_of_obj = sizeof(*this); - m_mode = cCRNMipModeUseSourceOrGenerateMips; - m_filter = cCRNMipFilterKaiser; - m_gamma_filtering = true; - m_gamma = 2.2f; - // Default "blurriness" factor of .9 actually sharpens the output a little. - m_blurriness = .9f; - m_renormalize = false; - m_tiled = false; - m_max_levels = cCRNMaxLevels; - m_min_mip_size = 1; - - m_scale_mode = cCRNSMDisabled; - m_scale_x = 1.0f; - m_scale_y = 1.0f; - - m_window_left = 0; - m_window_top = 0; - m_window_right = 0; - m_window_bottom = 0; - - m_clamp_scale = false; - m_clamp_width = 0; - m_clamp_height = 0; - } - - inline bool check() const { return true; } - - inline bool operator== (const crn_mipmap_params& rhs) const - { -#define CRNLIB_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0) - CRNLIB_COMP(m_size_of_obj); - CRNLIB_COMP(m_mode); - CRNLIB_COMP(m_filter); - CRNLIB_COMP(m_gamma_filtering); - CRNLIB_COMP(m_gamma); - CRNLIB_COMP(m_blurriness); - CRNLIB_COMP(m_renormalize); - CRNLIB_COMP(m_tiled); - CRNLIB_COMP(m_max_levels); - CRNLIB_COMP(m_min_mip_size); - CRNLIB_COMP(m_scale_mode); - CRNLIB_COMP(m_scale_x); - CRNLIB_COMP(m_scale_y); - CRNLIB_COMP(m_window_left); - CRNLIB_COMP(m_window_top); - CRNLIB_COMP(m_window_right); - CRNLIB_COMP(m_window_bottom); - CRNLIB_COMP(m_clamp_scale); - CRNLIB_COMP(m_clamp_width); - CRNLIB_COMP(m_clamp_height); - return true; -#undef CRNLIB_COMP - } - crn_uint32 m_size_of_obj; - - crn_mip_mode m_mode; - crn_mip_filter m_filter; - - crn_bool m_gamma_filtering; - float m_gamma; - - float m_blurriness; - - crn_uint32 m_max_levels; - crn_uint32 m_min_mip_size; - - crn_bool m_renormalize; - crn_bool m_tiled; - - crn_scale_mode m_scale_mode; - float m_scale_x; - float m_scale_y; - - crn_uint32 m_window_left; - crn_uint32 m_window_top; - crn_uint32 m_window_right; - crn_uint32 m_window_bottom; - - crn_bool m_clamp_scale; - crn_uint32 m_clamp_width; - crn_uint32 m_clamp_height; -}; - -// -------- High-level helper function definitions for CDN/DDS compression. - -#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT -#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2 -#endif - -// Function to set an optional user provided memory allocation/reallocation/msize routines. -// By default, crnlib just uses malloc(), free(), etc. for all allocations. -typedef void* (*crn_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data); -typedef size_t (*crn_msize_func)(void* p, void* pUser_data); -void crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data); - -// Frees memory blocks allocated by crn_compress(), crn_decompress_crn_to_dds(), or crn_decompress_dds_to_images(). -void crn_free_block(void *pBlock); - -// Compresses a 32-bit/pixel texture to either: a regular DX9 DDS file, a "clustered" (or reduced entropy) DX9 DDS file, or a CRN file in memory. -// Input parameters: -// comp_params is the compression parameters struct, defined above. -// compressed_size will be set to the size of the returned memory block containing the output file. -// The returned block must be freed by calling crn_free_block(). -// *pActual_quality_level will be set to the actual quality level used to compress the image. May be NULL. -// *pActual_bitrate will be set to the output file's effective bitrate, possibly taking into account LZMA compression. May be NULL. -// Return value: -// The compressed file data, or NULL on failure. -// compressed_size will be set to the size of the returned memory buffer. -// Notes: -// A "regular" DDS file is compressed using normal DXTn compression at the specified DXT quality level. -// A "clustered" DDS file is compressed using clustered DXTn compression to either the target bitrate or the specified integer quality factor. -// The output file is a standard DX9 format DDS file, except the compressor assumes you will be later losslessly compressing the DDS output file using the LZMA algorithm. -// A texture is defined as an array of 1 or 6 "faces" (6 faces=cubemap), where each "face" consists of between [1,cCRNMaxLevels] mipmap levels. -// Mipmap levels are simple 32-bit 2D images with a pitch of width*sizeof(uint32), arranged in the usual raster order (top scanline first). -// The image pixels may be grayscale (YYYX bytes in memory), grayscale/alpha (YYYA in memory), 24-bit (RGBX in memory), or 32-bit (RGBA) colors (where "X"=don't care). -// RGB color data is generally assumed to be in the sRGB colorspace. If not, be sure to clear the "cCRNCompFlagPerceptual" in the crn_comp_params struct! -void *crn_compress(const crn_comp_params &comp_params, crn_uint32 &compressed_size, crn_uint32 *pActual_quality_level = NULL, float *pActual_bitrate = NULL); - -// Like the above function, except this function can also do things like generate mipmaps, and resize or crop the input texture before compression. -// The actual operations performed are controlled by the crn_mipmap_params struct members. -// Be sure to set the "m_gamma_filtering" member of crn_mipmap_params to false if the input texture is not sRGB. -void *crn_compress(const crn_comp_params &comp_params, const crn_mipmap_params &mip_params, crn_uint32 &compressed_size, crn_uint32 *pActual_quality_level = NULL, float *pActual_bitrate = NULL); - -// Transcodes an entire CRN file to DDS using the crn_decomp.h header file library to do most of the heavy lifting. -// The output DDS file's format is guaranteed to be one of the DXTn formats in the crn_format enum. -// This is a fast operation, because the CRN format is explicitly designed to be efficiently transcodable to DXTn. -// For more control over decompression, see the lower-level helper functions in crn_decomp.h, which do not depend at all on crnlib. -void *crn_decompress_crn_to_dds(const void *pCRN_file_data, crn_uint32 &file_size); - -// Decompresses an entire DDS file in any supported format to uncompressed 32-bit/pixel image(s). -// See the crnlib::pixel_format enum in inc/dds_defs.h for a list of the supported DDS formats. -// You are responsible for freeing each image block, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer. -struct crn_texture_desc -{ - crn_uint32 m_faces; - crn_uint32 m_width; - crn_uint32 m_height; - crn_uint32 m_levels; - crn_uint32 m_fmt_fourcc; // Same as crnlib::pixel_format -}; -bool crn_decompress_dds_to_images(const void *pDDS_file_data, crn_uint32 dds_file_size, crn_uint32 **ppImages, crn_texture_desc &tex_desc); - -// Frees all images allocated by crn_decompress_dds_to_images(). -void crn_free_all_images(crn_uint32 **ppImages, const crn_texture_desc &desc); - -// -------- crn_format related helpers functions. - -// Returns the FOURCC format equivalent to the specified crn_format. -crn_uint32 crn_get_format_fourcc(crn_format fmt); - -// Returns the crn_format's bits per texel. -crn_uint32 crn_get_format_bits_per_texel(crn_format fmt); - -// Returns the crn_format's number of bytes per block. -crn_uint32 crn_get_bytes_per_dxt_block(crn_format fmt); - -// Returns the non-swizzled, basic DXTn version of the specified crn_format. -// This is the format you would supply D3D or OpenGL. -crn_format crn_get_fundamental_dxt_format(crn_format fmt); - -// -------- String helpers. - -// Converts a crn_file_type to a string. -const char* crn_get_file_type_ext(crn_file_type file_type); - -// Converts a crn_format to a string. -const char* crn_get_format_string(crn_format fmt); - -// Converts a crn_dxt_quality to a string. -const char* crn_get_dxt_quality_string(crn_dxt_quality q); - -// -------- Low-level DXTn 4x4 block compressor API - -// crnlib's DXTn endpoint optimizer actually supports any number of source pixels (i.e. from 1 to thousands, not just 16), -// but for simplicity this API only supports 4x4 texel blocks. -typedef void *crn_block_compressor_context_t; - -// Create a DXTn block compressor. -// This function only supports the basic/nonswizzled "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX. -// Avoid calling this multiple times if you intend on compressing many blocks, because it allocates some memory. -crn_block_compressor_context_t crn_create_block_compressor(const crn_comp_params ¶ms); - -// Compresses a block of 16 pixels to the destination DXTn block. -// pDst_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others). -// pPixels should be an array of 16 crn_uint32's. Each crn_uint32 must be r,g,b,a (r is always first) in memory. -void crn_compress_block(crn_block_compressor_context_t pContext, const crn_uint32 *pPixels, void *pDst_block); - -// Frees a DXTn block compressor. -void crn_free_block_compressor(crn_block_compressor_context_t pContext); - -// Unpacks a compressed block to pDst_pixels. -// pSrc_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others). -// pDst_pixel should be an array of 16 crn_uint32's. Each uint32 will be r,g,b,a (r is always first) in memory. -// crn_fmt should be one of the "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX. -// The various swizzled DXT5 formats (such as cCRNFmtDXT5_xGBR, etc.) will be unpacked as if they where plain DXT5. -// Returns false if the crn_fmt is invalid. -bool crn_decompress_block(const void *pSrc_block, crn_uint32 *pDst_pixels, crn_format crn_fmt); - -#endif // CRNLIB_H - -//------------------------------------------------------------------------------ -// -// crunch/crnlib uses a modified ZLIB license. Specifically, it's the same as zlib except that -// public credits for using the library are *required*. -// -// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved. -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// 2. If you use this software in a product, this acknowledgment in the product -// documentation or credits is required: -// -// "Crunch Library Copyright (c) 2010-2016 Richard Geldreich, Jr." -// -// 3. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 4. This notice may not be removed or altered from any source distribution. -// -//------------------------------------------------------------------------------ diff --git a/Texture2DDecoderNative/dllexport.h b/Texture2DDecoderNative/dllexport.h deleted file mode 100644 index 8a54c4a..0000000 --- a/Texture2DDecoderNative/dllexport.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#if defined(_MSC_VER) -#if _MSC_VER < 1910 // MSVC 2017- -#error MSVC 2017 or later is required. -#endif -#endif - -#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__) -#ifdef _T2D_DLL -#ifdef __GNUC__ -#define _T2D_EXPORT __attribute__ ((dllexport)) -#else -#define _T2D_EXPORT __declspec(dllexport) -#endif -#else -#ifdef __GNUC__ -#define _T2D_EXPORT __attribute__ ((dllimport)) -#else -#define _T2D_EXPORT __declspec(dllimport) -#endif -#endif -#define _T2D_LOCAL -#else -#if __GNUC__ >= 4 -#define _T2D_EXPORT __attribute__ ((visibility ("default"))) -#define _T2D_LOCAL __attribute__ ((visibility ("hidden"))) -#else -#define _T2D_EXPORT -#define _T2D_LOCAL -#endif -#endif - -#ifdef __cplusplus -#ifndef _EXTERN_C_STMT -#define _EXTERN_C_STMT extern "C" -#endif -#else -#ifndef _EXTERN_C_STMT -#define _EXTERN_C_STMT -#endif -#endif - -#ifndef _T2D_CALL -#if defined(WIN32) || defined(_WIN32) -#define _T2D_CALL __stdcall -#else -#define _T2D_CALL /* __cdecl */ -#endif -#endif - -#if defined(_MSC_VER) -#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT ret_type _T2D_CALL -#else -#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT _T2D_CALL ret_type -#endif diff --git a/Texture2DDecoderNative/dllmain.cpp b/Texture2DDecoderNative/dllmain.cpp deleted file mode 100644 index 086fe7b..0000000 --- a/Texture2DDecoderNative/dllmain.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "dllexport.h" -#include "bool32_t.h" - -#include "bcn.h" -#include "pvrtc.h" -#include "etc.h" -#include "atc.h" -#include "astc.h" -#include "crunch.h" -#include "unitycrunch.h" - -T2D_API(bool32_t) DecodeDXT1(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc1(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeDXT5(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc3(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodePVRTC(const void* data, int32_t width, int32_t height, void* image, bool32_t is2bpp) -{ - return decode_pvrtc(static_cast(data), width, height, static_cast(image), is2bpp ? 1 : 0); -} - -T2D_API(bool32_t) DecodeETC1(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_etc1(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeETC2(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_etc2(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeETC2A1(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_etc2a1(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeETC2A8(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_etc2a8(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeEACR(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_eacr(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeEACRSigned(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_eacr_signed(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeEACRG(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_eacrg(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeEACRGSigned(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_eacrg_signed(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeBC4(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc4(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeBC5(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc5(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeBC6(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc6(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeBC7(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_bc7(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeATCRGB4(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_atc_rgb4(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeATCRGBA8(const void* data, int32_t width, int32_t height, void* image) -{ - return decode_atc_rgba8(static_cast(data), width, height, static_cast(image)); -} - -T2D_API(bool32_t) DecodeASTC(const void* data, int32_t width, int32_t height, int32_t blockWidth, int32_t blockHeight, void* image) -{ - return decode_astc(static_cast(data), width, height, blockWidth, blockHeight, static_cast(image)); -} - -T2D_API(void) DisposeBuffer(void** ppBuffer) -{ - if (ppBuffer == nullptr) - { - return; - } - - auto ppTypedBuffer = reinterpret_cast(ppBuffer); - - delete[](*ppTypedBuffer); - - *ppBuffer = nullptr; -} - -T2D_API(void) UnpackCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize) -{ - void* result; - uint32_t resultSize; - - if (ppResult != nullptr) - { - *ppResult = nullptr; - } - - if (pResultSize != nullptr) - { - *pResultSize = 0; - } - - if (!crunch_unpack_level(static_cast(data), dataSize, 0, &result, &resultSize)) { - return; - } - - if (ppResult != nullptr) - { - *ppResult = result; - } - - if (pResultSize != nullptr) - { - *pResultSize = resultSize; - } -} - -T2D_API(void) UnpackUnityCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize) -{ - void* result; - uint32_t resultSize; - - if (ppResult != nullptr) - { - *ppResult = nullptr; - } - - if (pResultSize != nullptr) - { - *pResultSize = 0; - } - - if (!unity_crunch_unpack_level(static_cast(data), dataSize, 0, &result, &resultSize)) { - return; - } - - if (ppResult != nullptr) - { - *ppResult = result; - } - - if (pResultSize != nullptr) - { - *pResultSize = resultSize; - } -} diff --git a/Texture2DDecoderNative/endianness.h b/Texture2DDecoderNative/endianness.h deleted file mode 100644 index 7866e3b..0000000 --- a/Texture2DDecoderNative/endianness.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * License Information - * - * endianness.h is derived from https://gist.github.com/jtbr/7a43e6281e6cca353b33ee501421860c - * The file is licensed under the MIT License shown below. - * - * - * The MIT License (MIT) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _ENDIANNESS_H -#define _ENDIANNESS_H - -#include -#include - -/* Detect platform endianness at compile time */ - -// If boost were available on all platforms, could use this instead to detect endianness -// #include - -// When available, these headers can improve platform endianness detection -#ifdef __has_include // C++17, supported as extension to C++11 in clang, GCC 5+, vs2015 -#if __has_include() -#include // gnu libc normally provides, linux -#elif __has_include() -#include //open bsd, macos -#elif __has_include() -#include // mingw, some bsd (not open/macos) -#elif __has_include() -#include // solaris -#endif -#endif - -#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || (defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) || \ - (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || (defined(__sun) && defined(__SVR4) && defined(_BIG_ENDIAN)) || \ - defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || \ - defined(__MIBSEB__) || defined(_M_PPC) -#define __BIG_ENDIAN__ -#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || /* gcc */ \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) /* linux header */ || \ - (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /* mingw header */ || \ - (defined(__sun) && defined(__SVR4) && defined(_LITTLE_ENDIAN)) || /* solaris */ \ - defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || \ - defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) || /* msvc for intel processors */ \ - defined(_M_ARM) /* msvc code on arm executes in little endian mode */ -#define __LITTLE_ENDIAN__ -#endif -#endif - -#ifdef bswap16 -#undef bswap16 -#endif -#ifdef bswap32 -#undef bswap32 -#endif -#ifdef bswap64 -#undef bswap64 -#endif - -/* Define byte-swap functions, using fast processor-native built-ins where possible */ -// needs to be first because msvc doesn't short-circuit after failing defined(__has_builtin) -#if defined(_MSC_VER) -#define bswap16(x) _byteswap_ushort((x)) -#define bswap32(x) _byteswap_ulong((x)) -#define bswap64(x) _byteswap_uint64((x)) -#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -#define bswap16(x) __builtin_bswap16((x)) -#define bswap32(x) __builtin_bswap32((x)) -#define bswap64(x) __builtin_bswap64((x)) -#elif defined(__has_builtin) && __has_builtin(__builtin_bswap64) -/* for clang; gcc 5 fails on this and && shortcircuit fails; must be after GCC check */ -#define bswap16(x) __builtin_bswap16((x)) -#define bswap32(x) __builtin_bswap32((x)) -#define bswap64(x) __builtin_bswap64((x)) -#else -/* even in this case, compilers often optimize by using native instructions */ -static inline uint16_t bswap16(uint16_t x) { - return (((x >> 8) & 0xffu) | ((x & 0xffu) << 8)); -} -static inline uint32_t bswap32(uint32_t x) { - return (((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) | ((x & 0x0000ff00u) << 8) | - ((x & 0x000000ffu) << 24)); -} -static inline uint64_t bswap64(uint64_t x) { - return (((x & 0xff00000000000000ull) >> 56) | ((x & 0x00ff000000000000ull) >> 40) | - ((x & 0x0000ff0000000000ull) >> 24) | ((x & 0x000000ff00000000ull) >> 8) | - ((x & 0x00000000ff000000ull) << 8) | ((x & 0x0000000000ff0000ull) << 24) | - ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56)); -} -#endif - - -/* Defines network - host byte swaps as needed depending upon platform endianness */ -// note that network order is big endian) - -#if defined(__LITTLE_ENDIAN__) -#define ntoh16(x) bswap16((x)) -#define hton16(x) bswap16((x)) -#define ntoh32(x) bswap32((x)) -#define hton32(x) bswap32((x)) -#define ntoh64(x) bswap64((x)) -#define hton64(x) bswap64((x)) -#define lton16(x) (x) -#define lton32(x) (x) -#define lton64(x) (x) -#define ltonf(x) (x) -#define ltond(x) (x) -#define bton16(x) bswap16((x)) -#define bton32(x) bswap32((x)) -#define bton64(x) bswap64((x)) -#define btonf(x) htonf((x)) -#define btond(x) htond((x)) -#elif defined(__BIG_ENDIAN__) -#define ntoh16(x) (x) -#define hton16(x) (x) -#define ntoh32(x) (x) -#define hton32(x) (x) -#define ntoh64(x) (x) -#define hton64(x) (x) -#define bton16(x) (x) -#define bton32(x) (x) -#define bton64(x) (x) -#define btonf(x) (x) -#define btond(x) (x) -#define lton16(x) bswap16((x)) -#define lton32(x) bswap32((x)) -#define lton64(x) bswap64((x)) -#define ltonf(x) htonf((x)) -#define ltond(x) htond((x)) -#else -#warning "UNKNOWN Platform / endianness; network / host byte swaps not defined." -#endif - - -//! Convert 32-bit float from host to network byte order -static inline float htonf(float f) { -#ifdef __cplusplus - static_assert(sizeof(float) == sizeof(uint32_t), "Unexpected float format"); - uint32_t val = hton32(*(reinterpret_cast(&f))); - return *(reinterpret_cast(&val)); -#else - uint32_t val = hton32(*(const uint32_t *)(&f)); - return *((float *)(&val)); -#endif -} -#define ntohf(x) htonf((x)) - -//! Convert 64-bit double from host to network byte order -static inline double htond(double f) { -#ifdef __cplusplus - static_assert(sizeof(double) == sizeof(uint64_t), "Unexpected double format"); - uint64_t val = hton64(*(reinterpret_cast(&f))); - return *(reinterpret_cast(&val)); -#else - uint64_t val = hton64(*(const uint64_t *)(&f)); - return *((double *)(&val)); -#endif -} -#define ntohd(x) htond((x)) - -#endif //_ENDIANNESS_H diff --git a/Texture2DDecoderNative/etc.cpp b/Texture2DDecoderNative/etc.cpp deleted file mode 100644 index 6b08758..0000000 --- a/Texture2DDecoderNative/etc.cpp +++ /dev/null @@ -1,443 +0,0 @@ -#include "etc.h" -#include -#include -#include "color.h" - -const uint_fast8_t WriteOrderTable[16] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; -const uint_fast8_t WriteOrderTableRev[16] = {15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0}; -const uint_fast8_t Etc1ModifierTable[8][2] = {{2, 8}, {5, 17}, {9, 29}, {13, 42}, - {18, 60}, {24, 80}, {33, 106}, {47, 183}}; -const uint_fast8_t Etc2aModifierTable[2][8][2] = { - {{0, 8}, {0, 17}, {0, 29}, {0, 42}, {0, 60}, {0, 80}, {0, 106}, {0, 183}}, - {{2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183}}}; -const uint_fast8_t Etc1SubblockTable[2][16] = {{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}}; -const uint_fast8_t Etc2DistanceTable[8] = {3, 6, 11, 16, 23, 32, 41, 64}; -const int_fast8_t Etc2AlphaModTable[16][8] = { - {-3, -6, -9, -15, 2, 5, 8, 14}, {-3, -7, -10, -13, 2, 6, 9, 12}, {-2, -5, -8, -13, 1, 4, 7, 12}, - {-2, -4, -6, -13, 1, 3, 5, 12}, {-3, -6, -8, -12, 2, 5, 7, 11}, {-3, -7, -9, -11, 2, 6, 8, 10}, - {-4, -7, -8, -11, 3, 6, 7, 10}, {-3, -5, -8, -11, 2, 4, 7, 10}, {-2, -6, -8, -10, 1, 5, 7, 9}, - {-2, -5, -8, -10, 1, 4, 7, 9}, {-2, -4, -8, -10, 1, 3, 7, 9}, {-2, -5, -7, -10, 1, 4, 6, 9}, - {-3, -4, -7, -10, 2, 3, 6, 9}, {-1, -2, -3, -10, 0, 1, 2, 9}, {-4, -6, -8, -9, 3, 5, 7, 8}, - {-3, -5, -7, -9, 2, 4, 6, 8}}; - -static inline uint_fast8_t clamp(const int n) { - return n < 0 ? 0 : n > 255 ? 255 : n; -} - -static inline uint32_t applicate_color(uint_fast8_t c[3], int_fast16_t m) { - return color(clamp(c[0] + m), clamp(c[1] + m), clamp(c[2] + m), 255); -} - -static inline uint32_t applicate_color_alpha(uint_fast8_t c[3], int_fast16_t m, int transparent) { - return color(clamp(c[0] + m), clamp(c[1] + m), clamp(c[2] + m), transparent ? 0 : 255); -} - -static inline uint32_t applicate_color_raw(uint_fast8_t c[3]) { - return color(c[0], c[1], c[2], 255); -} - -static void decode_etc1_block(const uint8_t *data, uint32_t *outbuf) { - const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7}; // Table codewords - const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1]; - uint_fast8_t c[2][3]; - if (data[3] & 2) { - // diff bit == 1 - c[0][0] = data[0] & 0xf8; - c[0][1] = data[1] & 0xf8; - c[0][2] = data[2] & 0xf8; - c[1][0] = c[0][0] + (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20); - c[1][1] = c[0][1] + (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20); - c[1][2] = c[0][2] + (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20); - c[0][0] |= c[0][0] >> 5; - c[0][1] |= c[0][1] >> 5; - c[0][2] |= c[0][2] >> 5; - c[1][0] |= c[1][0] >> 5; - c[1][1] |= c[1][1] >> 5; - c[1][2] |= c[1][2] >> 5; - } else { - // diff bit == 0 - c[0][0] = (data[0] & 0xf0) | data[0] >> 4; - c[1][0] = (data[0] & 0x0f) | data[0] << 4; - c[0][1] = (data[1] & 0xf0) | data[1] >> 4; - c[1][1] = (data[1] & 0x0f) | data[1] << 4; - c[0][2] = (data[2] & 0xf0) | data[2] >> 4; - c[1][2] = (data[2] & 0x0f) | data[2] << 4; - } - - uint_fast16_t j = data[6] << 8 | data[7]; // less significant pixel index bits - uint_fast16_t k = data[4] << 8 | data[5]; // more significant pixel index bits - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - uint_fast8_t s = table[i]; - uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1]; - outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m); - } -} - -static void decode_etc2_block(const uint8_t *data, uint32_t *outbuf) { - uint_fast16_t j = data[6] << 8 | data[7]; // 15 -> 0 - uint_fast32_t k = data[4] << 8 | data[5]; // 31 -> 16 - uint_fast8_t c[3][3] = {}; - - if (data[3] & 2) { - // diff bit == 1 - uint_fast8_t r = data[0] & 0xf8; - int_fast16_t dr = (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20); - uint_fast8_t g = data[1] & 0xf8; - int_fast16_t dg = (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20); - uint_fast8_t b = data[2] & 0xf8; - int_fast16_t db = (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20); - if (r + dr < 0 || r + dr > 255) { - // T - c[0][0] = (data[0] << 3 & 0xc0) | (data[0] << 4 & 0x30) | (data[0] >> 1 & 0xc) | (data[0] & 3); - c[0][1] = (data[1] & 0xf0) | data[1] >> 4; - c[0][2] = (data[1] & 0x0f) | data[1] << 4; - c[1][0] = (data[2] & 0xf0) | data[2] >> 4; - c[1][1] = (data[2] & 0x0f) | data[2] << 4; - c[1][2] = (data[3] & 0xf0) | data[3] >> 4; - const uint_fast8_t d = Etc2DistanceTable[(data[3] >> 1 & 6) | (data[3] & 1)]; - uint_fast32_t color_set[4] = {applicate_color_raw(c[0]), applicate_color(c[1], d), - applicate_color_raw(c[1]), applicate_color(c[1], -d)}; - k <<= 1; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) - outbuf[WriteOrderTable[i]] = color_set[(k & 2) | (j & 1)]; - } else if (g + dg < 0 || g + dg > 255) { - // H - c[0][0] = (data[0] << 1 & 0xf0) | (data[0] >> 3 & 0xf); - c[0][1] = (data[0] << 5 & 0xe0) | (data[1] & 0x10); - c[0][1] |= c[0][1] >> 4; - c[0][2] = (data[1] & 8) | (data[1] << 1 & 6) | data[2] >> 7; - c[0][2] |= c[0][2] << 4; - c[1][0] = (data[2] << 1 & 0xf0) | (data[2] >> 3 & 0xf); - c[1][1] = (data[2] << 5 & 0xe0) | (data[3] >> 3 & 0x10); - c[1][1] |= c[1][1] >> 4; - c[1][2] = (data[3] << 1 & 0xf0) | (data[3] >> 3 & 0xf); - uint_fast8_t d = (data[3] & 4) | (data[3] << 1 & 2); - if (c[0][0] > c[1][0] || - (c[0][0] == c[1][0] && (c[0][1] > c[1][1] || (c[0][1] == c[1][1] && c[0][2] >= c[1][2])))) - ++d; - d = Etc2DistanceTable[d]; - uint_fast32_t color_set[4] = {applicate_color(c[0], d), applicate_color(c[0], -d), applicate_color(c[1], d), - applicate_color(c[1], -d)}; - k <<= 1; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) - outbuf[WriteOrderTable[i]] = color_set[(k & 2) | (j & 1)]; - } else if (b + db < 0 || b + db > 255) { - // planar - c[0][0] = (data[0] << 1 & 0xfc) | (data[0] >> 5 & 3); - c[0][1] = (data[0] << 7 & 0x80) | (data[1] & 0x7e) | (data[0] & 1); - c[0][2] = (data[1] << 7 & 0x80) | (data[2] << 2 & 0x60) | (data[2] << 3 & 0x18) | (data[3] >> 5 & 4); - c[0][2] |= c[0][2] >> 6; - c[1][0] = (data[3] << 1 & 0xf8) | (data[3] << 2 & 4) | (data[3] >> 5 & 3); - c[1][1] = (data[4] & 0xfe) | data[4] >> 7; - c[1][2] = (data[4] << 7 & 0x80) | (data[5] >> 1 & 0x7c); - c[1][2] |= c[1][2] >> 6; - c[2][0] = (data[5] << 5 & 0xe0) | (data[6] >> 3 & 0x1c) | (data[5] >> 1 & 3); - c[2][1] = (data[6] << 3 & 0xf8) | (data[7] >> 5 & 0x6) | (data[6] >> 4 & 1); - c[2][2] = data[7] << 2 | (data[7] >> 4 & 3); - for (int y = 0, i = 0; y < 4; y++) { - for (int x = 0; x < 4; x++, i++) { - uint8_t r = clamp((x * (c[1][0] - c[0][0]) + y * (c[2][0] - c[0][0]) + 4 * c[0][0] + 2) >> 2); - uint8_t g = clamp((x * (c[1][1] - c[0][1]) + y * (c[2][1] - c[0][1]) + 4 * c[0][1] + 2) >> 2); - uint8_t b = clamp((x * (c[1][2] - c[0][2]) + y * (c[2][2] - c[0][2]) + 4 * c[0][2] + 2) >> 2); - outbuf[i] = color(r, g, b, 255); - } - } - } else { - // differential - const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7}; - const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1]; - c[0][0] = r | r >> 5; - c[0][1] = g | g >> 5; - c[0][2] = b | b >> 5; - c[1][0] = r + dr; - c[1][1] = g + dg; - c[1][2] = b + db; - c[1][0] |= c[1][0] >> 5; - c[1][1] |= c[1][1] >> 5; - c[1][2] |= c[1][2] >> 5; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - uint_fast8_t s = table[i]; - uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1]; - outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m); - } - } - } else { - // individual (diff bit == 0) - const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7}; - const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1]; - c[0][0] = (data[0] & 0xf0) | data[0] >> 4; - c[1][0] = (data[0] & 0x0f) | data[0] << 4; - c[0][1] = (data[1] & 0xf0) | data[1] >> 4; - c[1][1] = (data[1] & 0x0f) | data[1] << 4; - c[0][2] = (data[2] & 0xf0) | data[2] >> 4; - c[1][2] = (data[2] & 0x0f) | data[2] << 4; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - uint_fast8_t s = table[i]; - uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1]; - outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m); - } - } -} - -static void decode_etc2a1_block(const uint8_t *data, uint32_t *outbuf) { - uint_fast16_t j = data[6] << 8 | data[7]; // 15 -> 0 - uint_fast32_t k = data[4] << 8 | data[5]; // 31 -> 16 - uint_fast8_t c[3][3] = {}; - - int obaq = data[3] >> 1 & 1; - - // diff bit == 1 - uint_fast8_t r = data[0] & 0xf8; - int_fast16_t dr = (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20); - uint_fast8_t g = data[1] & 0xf8; - int_fast16_t dg = (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20); - uint_fast8_t b = data[2] & 0xf8; - int_fast16_t db = (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20); - if (r + dr < 0 || r + dr > 255) { - // T - c[0][0] = (data[0] << 3 & 0xc0) | (data[0] << 4 & 0x30) | (data[0] >> 1 & 0xc) | (data[0] & 3); - c[0][1] = (data[1] & 0xf0) | data[1] >> 4; - c[0][2] = (data[1] & 0x0f) | data[1] << 4; - c[1][0] = (data[2] & 0xf0) | data[2] >> 4; - c[1][1] = (data[2] & 0x0f) | data[2] << 4; - c[1][2] = (data[3] & 0xf0) | data[3] >> 4; - const uint_fast8_t d = Etc2DistanceTable[(data[3] >> 1 & 6) | (data[3] & 1)]; - uint_fast32_t color_set[4] = {applicate_color_raw(c[0]), applicate_color(c[1], d), applicate_color_raw(c[1]), - applicate_color(c[1], -d)}; - k <<= 1; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - int index = (k & 2) | (j & 1); - outbuf[WriteOrderTable[i]] = color_set[index]; - if (!obaq && index == 2) - outbuf[WriteOrderTable[i]] &= TRANSPARENT_MASK; - } - } else if (g + dg < 0 || g + dg > 255) { - // H - c[0][0] = (data[0] << 1 & 0xf0) | (data[0] >> 3 & 0xf); - c[0][1] = (data[0] << 5 & 0xe0) | (data[1] & 0x10); - c[0][1] |= c[0][1] >> 4; - c[0][2] = (data[1] & 8) | (data[1] << 1 & 6) | data[2] >> 7; - c[0][2] |= c[0][2] << 4; - c[1][0] = (data[2] << 1 & 0xf0) | (data[2] >> 3 & 0xf); - c[1][1] = (data[2] << 5 & 0xe0) | (data[3] >> 3 & 0x10); - c[1][1] |= c[1][1] >> 4; - c[1][2] = (data[3] << 1 & 0xf0) | (data[3] >> 3 & 0xf); - uint_fast8_t d = (data[3] & 4) | (data[3] << 1 & 2); - if (c[0][0] > c[1][0] || - (c[0][0] == c[1][0] && (c[0][1] > c[1][1] || (c[0][1] == c[1][1] && c[0][2] >= c[1][2])))) - ++d; - d = Etc2DistanceTable[d]; - uint_fast32_t color_set[4] = {applicate_color(c[0], d), applicate_color(c[0], -d), applicate_color(c[1], d), - applicate_color(c[1], -d)}; - k <<= 1; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - int index = (k & 2) | (j & 1); - outbuf[WriteOrderTable[i]] = color_set[index]; - if (!obaq && index == 2) - outbuf[WriteOrderTable[i]] &= TRANSPARENT_MASK; - } - } else if (b + db < 0 || b + db > 255) { - // planar - c[0][0] = (data[0] << 1 & 0xfc) | (data[0] >> 5 & 3); - c[0][1] = (data[0] << 7 & 0x80) | (data[1] & 0x7e) | (data[0] & 1); - c[0][2] = (data[1] << 7 & 0x80) | (data[2] << 2 & 0x60) | (data[2] << 3 & 0x18) | (data[3] >> 5 & 4); - c[0][2] |= c[0][2] >> 6; - c[1][0] = (data[3] << 1 & 0xf8) | (data[3] << 2 & 4) | (data[3] >> 5 & 3); - c[1][1] = (data[4] & 0xfe) | data[4] >> 7; - c[1][2] = (data[4] << 7 & 0x80) | (data[5] >> 1 & 0x7c); - c[1][2] |= c[1][2] >> 6; - c[2][0] = (data[5] << 5 & 0xe0) | (data[6] >> 3 & 0x1c) | (data[5] >> 1 & 3); - c[2][1] = (data[6] << 3 & 0xf8) | (data[7] >> 5 & 0x6) | (data[6] >> 4 & 1); - c[2][2] = data[7] << 2 | (data[7] >> 4 & 3); - for (int y = 0, i = 0; y < 4; y++) { - for (int x = 0; x < 4; x++, i++) { - uint8_t r = clamp((x * (c[1][0] - c[0][0]) + y * (c[2][0] - c[0][0]) + 4 * c[0][0] + 2) >> 2); - uint8_t g = clamp((x * (c[1][1] - c[0][1]) + y * (c[2][1] - c[0][1]) + 4 * c[0][1] + 2) >> 2); - uint8_t b = clamp((x * (c[1][2] - c[0][2]) + y * (c[2][2] - c[0][2]) + 4 * c[0][2] + 2) >> 2); - outbuf[i] = color(r, g, b, 255); - } - } - } else { - // differential - const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7}; - const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1]; - c[0][0] = r | r >> 5; - c[0][1] = g | g >> 5; - c[0][2] = b | b >> 5; - c[1][0] = r + dr; - c[1][1] = g + dg; - c[1][2] = b + db; - c[1][0] |= c[1][0] >> 5; - c[1][1] |= c[1][1] >> 5; - c[1][2] |= c[1][2] >> 5; - for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) { - uint_fast8_t s = table[i]; - uint_fast8_t m = Etc2aModifierTable[obaq][code[s]][j & 1]; - outbuf[WriteOrderTable[i]] = applicate_color_alpha(c[s], k & 1 ? -m : m, !obaq && (k & 1) && !(j & 1)); - } - } -} - -static void decode_etc2a8_block(const uint8_t *data, uint32_t *outbuf) { - if (data[1] & 0xf0) { - // multiplier != 0 - const uint_fast8_t multiplier = data[1] >> 4; - const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf]; - uint_fast64_t l = bton64(*(uint64_t*)data); - for (int i = 0; i < 16; i++, l >>= 3) - ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[3] = clamp(data[0] + multiplier * table[l & 7]); - } else { - // multiplier == 0 (always same as base codeword) - for (int i = 0; i < 16; i++, outbuf++) - ((uint8_t *)outbuf)[3] = data[0]; - } -} - -static void decode_eac_block(const uint8_t *data, int color, uint32_t *outbuf) { - uint_fast8_t multiplier = data[1] >> 1 & 0x78; - if (multiplier == 0) - multiplier = 1; - const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf]; - uint_fast64_t l = bton64(*(uint64_t*)data); - for (int i = 0; i < 16; i++, l >>= 3) { - int_fast16_t val = data[0] * 8 + multiplier * table[l & 7] + 4; - ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3; - } -} - -static void decode_eac_signed_block(const uint8_t *data, int color, uint32_t *outbuf) { - int8_t base = (int8_t)data[0]; - uint_fast8_t multiplier = data[1] >> 1 & 0x78; - if (multiplier == 0) - multiplier = 1; - const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf]; - uint_fast64_t l = bton64(*(uint64_t*)data); - for (int i = 0; i < 16; i++, l >>= 3) { - int_fast16_t val = base * 8 + multiplier * table[l & 7] + 1023; - ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3; - } -} - -int decode_etc1(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 8) { - decode_etc1_block(data, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_etc2(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 8) { - decode_etc2_block(data, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_etc2a1(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 8) { - decode_etc2a1_block(data, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_etc2a8(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 16) { - decode_etc2_block(data + 8, buffer); - decode_etc2a8_block(data, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_eacr(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - uint32_t base_buffer[16]; - for (int i = 0; i < 16; i++) - base_buffer[i] = color(0, 0, 0, 255); - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 8) { - memcpy(buffer, base_buffer, sizeof(buffer)); - decode_eac_block(data, 2, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_eacr_signed(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - uint32_t base_buffer[16]; - for (int i = 0; i < 16; i++) - base_buffer[i] = color(0, 0, 0, 255); - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 8) { - memcpy(buffer, base_buffer, sizeof(buffer)); - decode_eac_signed_block(data, 2, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_eacrg(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - uint32_t base_buffer[16]; - for (int i = 0; i < 16; i++) - base_buffer[i] = color(0, 0, 0, 255); - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 16) { - memcpy(buffer, base_buffer, sizeof(buffer)); - decode_eac_block(data, 2, buffer); - decode_eac_block(data + 8, 1, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} - -int decode_eacrg_signed(const uint8_t *data, const long w, const long h, uint32_t *image) { - long num_blocks_x = (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - uint32_t buffer[16]; - uint32_t base_buffer[16]; - for (int i = 0; i < 16; i++) - base_buffer[i] = color(0, 0, 0, 255); - for (long by = 0; by < num_blocks_y; by++) { - for (long bx = 0; bx < num_blocks_x; bx++, data += 16) { - memcpy(buffer, base_buffer, sizeof(buffer)); - decode_eac_signed_block(data, 2, buffer); - decode_eac_signed_block(data + 8, 1, buffer); - copy_block_buffer(bx, by, w, h, 4, 4, buffer, image); - } - } - return 1; -} diff --git a/Texture2DDecoderNative/etc.h b/Texture2DDecoderNative/etc.h deleted file mode 100644 index 5546b8a..0000000 --- a/Texture2DDecoderNative/etc.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ETC_H -#define ETC_H - -#include - -int decode_etc1(const uint8_t *, const long, const long, uint32_t *); -int decode_etc2(const uint8_t *, const long, const long, uint32_t *); -int decode_etc2a1(const uint8_t *, const long, const long, uint32_t *); -int decode_etc2a8(const uint8_t *, const long, const long, uint32_t *); -int decode_eacr(const uint8_t *, const long, const long, uint32_t *); -int decode_eacr_signed(const uint8_t *, const long, const long, uint32_t *); -int decode_eacrg(const uint8_t *, const long, const long, uint32_t *); -int decode_eacrg_signed(const uint8_t *, const long, const long, uint32_t *); - -#endif /* end of include guard: ETC_H */ diff --git a/Texture2DDecoderNative/fp16.h b/Texture2DDecoderNative/fp16.h deleted file mode 100644 index b7f0c1d..0000000 --- a/Texture2DDecoderNative/fp16.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#ifndef FP16_H -#define FP16_H - -#include "fp16/fp16.h" - -#endif /* FP16_H */ - -/* - * - * License Information - * - * FP16 library is derived from https://github.com/Maratyszcza/FP16. - * The library is licensed under the MIT License shown below. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Facebook Inc. - * Copyright (c) 2017 Georgia Institute of Technology - * Copyright 2019 Google LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ diff --git a/Texture2DDecoderNative/fp16/bitcasts.h b/Texture2DDecoderNative/fp16/bitcasts.h deleted file mode 100644 index 26a755c..0000000 --- a/Texture2DDecoderNative/fp16/bitcasts.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#ifndef FP16_BITCASTS_H -#define FP16_BITCASTS_H - -#if defined(__cplusplus) && (__cplusplus >= 201103L) - #include -#elif !defined(__OPENCL_VERSION__) - #include -#endif - - -static inline float fp32_from_bits(uint32_t w) { -#if defined(__OPENCL_VERSION__) - return as_float(w); -#elif defined(__CUDA_ARCH__) - return __uint_as_float((unsigned int) w); -#elif defined(__INTEL_COMPILER) - return _castu32_f32(w); -#else - union { - uint32_t as_bits; - float as_value; - } fp32 = { w }; - return fp32.as_value; -#endif -} - -static inline uint32_t fp32_to_bits(float f) { -#if defined(__OPENCL_VERSION__) - return as_uint(f); -#elif defined(__CUDA_ARCH__) - return (uint32_t) __float_as_uint(f); -#elif defined(__INTEL_COMPILER) - return _castf32_u32(f); -#else - union { - float as_value; - uint32_t as_bits; - } fp32 = { f }; - return fp32.as_bits; -#endif -} - -static inline double fp64_from_bits(uint64_t w) { -#if defined(__OPENCL_VERSION__) - return as_double(w); -#elif defined(__CUDA_ARCH__) - return __longlong_as_double((long long) w); -#elif defined(__INTEL_COMPILER) - return _castu64_f64(w); -#else - union { - uint64_t as_bits; - double as_value; - } fp64 = { w }; - return fp64.as_value; -#endif -} - -static inline uint64_t fp64_to_bits(double f) { -#if defined(__OPENCL_VERSION__) - return as_ulong(f); -#elif defined(__CUDA_ARCH__) - return (uint64_t) __double_as_longlong(f); -#elif defined(__INTEL_COMPILER) - return _castf64_u64(f); -#else - union { - double as_value; - uint64_t as_bits; - } fp64 = { f }; - return fp64.as_bits; -#endif -} - -#endif /* FP16_BITCASTS_H */ diff --git a/Texture2DDecoderNative/fp16/fp16.h b/Texture2DDecoderNative/fp16/fp16.h deleted file mode 100644 index 642f2f8..0000000 --- a/Texture2DDecoderNative/fp16/fp16.h +++ /dev/null @@ -1,451 +0,0 @@ -#pragma once -#ifndef FP16_FP16_H -#define FP16_FP16_H - -#if defined(__cplusplus) && (__cplusplus >= 201103L) - #include - #include -#elif !defined(__OPENCL_VERSION__) - #include - #include -#endif - -#ifdef _MSC_VER - #include -#endif - -#include "fp16/bitcasts.h" - - -/* - * Convert a 16-bit floating-point number in IEEE half-precision format, in bit representation, to - * a 32-bit floating-point number in IEEE single-precision format, in bit representation. - * - * @note The implementation doesn't use any floating-point operations. - */ -static inline uint32_t fp16_ieee_to_fp32_bits(uint16_t h) { - /* - * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word: - * +---+-----+------------+-------------------+ - * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 31 26-30 16-25 0-15 - * - * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits. - */ - const uint32_t w = (uint32_t) h << 16; - /* - * Extract the sign of the input number into the high bit of the 32-bit word: - * - * +---+----------------------------------+ - * | S |0000000 00000000 00000000 00000000| - * +---+----------------------------------+ - * Bits 31 0-31 - */ - const uint32_t sign = w & UINT32_C(0x80000000); - /* - * Extract mantissa and biased exponent of the input number into the bits 0-30 of the 32-bit word: - * - * +---+-----+------------+-------------------+ - * | 0 |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 30 27-31 17-26 0-16 - */ - const uint32_t nonsign = w & UINT32_C(0x7FFFFFFF); - /* - * Renorm shift is the number of bits to shift mantissa left to make the half-precision number normalized. - * If the initial number is normalized, some of its high 6 bits (sign == 0 and 5-bit exponent) equals one. - * In this case renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note that if we shift - * denormalized nonsign by renorm_shift, the unit bit of mantissa will shift into exponent, turning the - * biased exponent into 1, and making mantissa normalized (i.e. without leading 1). - */ -#ifdef _MSC_VER - unsigned long nonsign_bsr; - _BitScanReverse(&nonsign_bsr, (unsigned long) nonsign); - uint32_t renorm_shift = (uint32_t) nonsign_bsr ^ 31; -#else - uint32_t renorm_shift = __builtin_clz(nonsign); -#endif - renorm_shift = renorm_shift > 5 ? renorm_shift - 5 : 0; - /* - * Iff half-precision number has exponent of 15, the addition overflows it into bit 31, - * and the subsequent shift turns the high 9 bits into 1. Thus - * inf_nan_mask == - * 0x7F800000 if the half-precision number had exponent of 15 (i.e. was NaN or infinity) - * 0x00000000 otherwise - */ - const int32_t inf_nan_mask = ((int32_t) (nonsign + 0x04000000) >> 8) & INT32_C(0x7F800000); - /* - * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 into 1. Otherwise, bit 31 remains 0. - * The signed shift right by 31 broadcasts bit 31 into all bits of the zero_mask. Thus - * zero_mask == - * 0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h) - * 0x00000000 otherwise - */ - const int32_t zero_mask = (int32_t) (nonsign - 1) >> 31; - /* - * 1. Shift nonsign left by renorm_shift to normalize it (if the input was denormal) - * 2. Shift nonsign right by 3 so the exponent (5 bits originally) becomes an 8-bit field and 10-bit mantissa - * shifts into the 10 high bits of the 23-bit mantissa of IEEE single-precision number. - * 3. Add 0x70 to the exponent (starting at bit 23) to compensate the different in exponent bias - * (0x7F for single-precision number less 0xF for half-precision number). - * 4. Subtract renorm_shift from the exponent (starting at bit 23) to account for renormalization. As renorm_shift - * is less than 0x70, this can be combined with step 3. - * 5. Binary OR with inf_nan_mask to turn the exponent into 0xFF if the input was NaN or infinity. - * 6. Binary ANDNOT with zero_mask to turn the mantissa and exponent into zero if the input was zero. - * 7. Combine with the sign of the input number. - */ - return sign | ((((nonsign << renorm_shift >> 3) + ((0x70 - renorm_shift) << 23)) | inf_nan_mask) & ~zero_mask); -} - -/* - * Convert a 16-bit floating-point number in IEEE half-precision format, in bit representation, to - * a 32-bit floating-point number in IEEE single-precision format. - * - * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals) - * floating-point operations and bitcasts between integer and floating-point variables. - */ -static inline float fp16_ieee_to_fp32_value(uint16_t h) { - /* - * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word: - * +---+-----+------------+-------------------+ - * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 31 26-30 16-25 0-15 - * - * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits. - */ - const uint32_t w = (uint32_t) h << 16; - /* - * Extract the sign of the input number into the high bit of the 32-bit word: - * - * +---+----------------------------------+ - * | S |0000000 00000000 00000000 00000000| - * +---+----------------------------------+ - * Bits 31 0-31 - */ - const uint32_t sign = w & UINT32_C(0x80000000); - /* - * Extract mantissa and biased exponent of the input number into the high bits of the 32-bit word: - * - * +-----+------------+---------------------+ - * |EEEEE|MM MMMM MMMM|0 0000 0000 0000 0000| - * +-----+------------+---------------------+ - * Bits 27-31 17-26 0-16 - */ - const uint32_t two_w = w + w; - - /* - * Shift mantissa and exponent into bits 23-28 and bits 13-22 so they become mantissa and exponent - * of a single-precision floating-point number: - * - * S|Exponent | Mantissa - * +-+---+-----+------------+----------------+ - * |0|000|EEEEE|MM MMMM MMMM|0 0000 0000 0000| - * +-+---+-----+------------+----------------+ - * Bits | 23-31 | 0-22 - * - * Next, there are some adjustments to the exponent: - * - The exponent needs to be corrected by the difference in exponent bias between single-precision and half-precision - * formats (0x7F - 0xF = 0x70) - * - Inf and NaN values in the inputs should become Inf and NaN values after conversion to the single-precision number. - * Therefore, if the biased exponent of the half-precision input was 0x1F (max possible value), the biased exponent - * of the single-precision output must be 0xFF (max possible value). We do this correction in two steps: - * - First, we adjust the exponent by (0xFF - 0x1F) = 0xE0 (see exp_offset below) rather than by 0x70 suggested - * by the difference in the exponent bias (see above). - * - Then we multiply the single-precision result of exponent adjustment by 2**(-112) to reverse the effect of - * exponent adjustment by 0xE0 less the necessary exponent adjustment by 0x70 due to difference in exponent bias. - * The floating-point multiplication hardware would ensure than Inf and NaN would retain their value on at least - * partially IEEE754-compliant implementations. - * - * Note that the above operations do not handle denormal inputs (where biased exponent == 0). However, they also do not - * operate on denormal inputs, and do not produce denormal results. - */ - const uint32_t exp_offset = UINT32_C(0xE0) << 23; -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__) - const float exp_scale = 0x1.0p-112f; -#else - const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)); -#endif - const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; - - /* - * Convert denormalized half-precision inputs into single-precision results (always normalized). - * Zero inputs are also handled here. - * - * In a denormalized number the biased exponent is zero, and mantissa has on-zero bits. - * First, we shift mantissa into bits 0-9 of the 32-bit word. - * - * zeros | mantissa - * +---------------------------+------------+ - * |0000 0000 0000 0000 0000 00|MM MMMM MMMM| - * +---------------------------+------------+ - * Bits 10-31 0-9 - * - * Now, remember that denormalized half-precision numbers are represented as: - * FP16 = mantissa * 2**(-24). - * The trick is to construct a normalized single-precision number with the same mantissa and thehalf-precision input - * and with an exponent which would scale the corresponding mantissa bits to 2**(-24). - * A normalized single-precision floating-point number is represented as: - * FP32 = (1 + mantissa * 2**(-23)) * 2**(exponent - 127) - * Therefore, when the biased exponent is 126, a unit change in the mantissa of the input denormalized half-precision - * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same ammount. - * - * The last step is to adjust the bias of the constructed single-precision number. When the input half-precision number - * is zero, the constructed single-precision number has the value of - * FP32 = 1 * 2**(126 - 127) = 2**(-1) = 0.5 - * Therefore, we need to subtract 0.5 from the constructed single-precision number to get the numerical equivalent of - * the input half-precision number. - */ - const uint32_t magic_mask = UINT32_C(126) << 23; - const float magic_bias = 0.5f; - const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; - - /* - * - Choose either results of conversion of input as a normalized number, or as a denormalized number, depending on the - * input exponent. The variable two_w contains input exponent in bits 27-31, therefore if its smaller than 2**27, the - * input is either a denormal number, or zero. - * - Combine the result of conversion of exponent and mantissa with the sign of the input number. - */ - const uint32_t denormalized_cutoff = UINT32_C(1) << 27; - const uint32_t result = sign | - (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value)); - return fp32_from_bits(result); -} - -/* - * Convert a 32-bit floating-point number in IEEE single-precision format to a 16-bit floating-point number in - * IEEE half-precision format, in bit representation. - * - * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals) - * floating-point operations and bitcasts between integer and floating-point variables. - */ -static inline uint16_t fp16_ieee_from_fp32_value(float f) { -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__) - const float scale_to_inf = 0x1.0p+112f; - const float scale_to_zero = 0x1.0p-110f; -#else - const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)); - const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)); -#endif - float base = (fabsf(f) * scale_to_inf) * scale_to_zero; - - const uint32_t w = fp32_to_bits(f); - const uint32_t shl1_w = w + w; - const uint32_t sign = w & UINT32_C(0x80000000); - uint32_t bias = shl1_w & UINT32_C(0xFF000000); - if (bias < UINT32_C(0x71000000)) { - bias = UINT32_C(0x71000000); - } - - base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; - const uint32_t bits = fp32_to_bits(base); - const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); - const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); - const uint32_t nonsign = exp_bits + mantissa_bits; - return (sign >> 16) | (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign); -} - -/* - * Convert a 16-bit floating-point number in ARM alternative half-precision format, in bit representation, to - * a 32-bit floating-point number in IEEE single-precision format, in bit representation. - * - * @note The implementation doesn't use any floating-point operations. - */ -static inline uint32_t fp16_alt_to_fp32_bits(uint16_t h) { - /* - * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word: - * +---+-----+------------+-------------------+ - * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 31 26-30 16-25 0-15 - * - * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits. - */ - const uint32_t w = (uint32_t) h << 16; - /* - * Extract the sign of the input number into the high bit of the 32-bit word: - * - * +---+----------------------------------+ - * | S |0000000 00000000 00000000 00000000| - * +---+----------------------------------+ - * Bits 31 0-31 - */ - const uint32_t sign = w & UINT32_C(0x80000000); - /* - * Extract mantissa and biased exponent of the input number into the bits 0-30 of the 32-bit word: - * - * +---+-----+------------+-------------------+ - * | 0 |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 30 27-31 17-26 0-16 - */ - const uint32_t nonsign = w & UINT32_C(0x7FFFFFFF); - /* - * Renorm shift is the number of bits to shift mantissa left to make the half-precision number normalized. - * If the initial number is normalized, some of its high 6 bits (sign == 0 and 5-bit exponent) equals one. - * In this case renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note that if we shift - * denormalized nonsign by renorm_shift, the unit bit of mantissa will shift into exponent, turning the - * biased exponent into 1, and making mantissa normalized (i.e. without leading 1). - */ -#ifdef _MSC_VER - unsigned long nonsign_bsr; - _BitScanReverse(&nonsign_bsr, (unsigned long) nonsign); - uint32_t renorm_shift = (uint32_t) nonsign_bsr ^ 31; -#else - uint32_t renorm_shift = __builtin_clz(nonsign); -#endif - renorm_shift = renorm_shift > 5 ? renorm_shift - 5 : 0; - /* - * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 into 1. Otherwise, bit 31 remains 0. - * The signed shift right by 31 broadcasts bit 31 into all bits of the zero_mask. Thus - * zero_mask == - * 0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h) - * 0x00000000 otherwise - */ - const int32_t zero_mask = (int32_t) (nonsign - 1) >> 31; - /* - * 1. Shift nonsign left by renorm_shift to normalize it (if the input was denormal) - * 2. Shift nonsign right by 3 so the exponent (5 bits originally) becomes an 8-bit field and 10-bit mantissa - * shifts into the 10 high bits of the 23-bit mantissa of IEEE single-precision number. - * 3. Add 0x70 to the exponent (starting at bit 23) to compensate the different in exponent bias - * (0x7F for single-precision number less 0xF for half-precision number). - * 4. Subtract renorm_shift from the exponent (starting at bit 23) to account for renormalization. As renorm_shift - * is less than 0x70, this can be combined with step 3. - * 5. Binary ANDNOT with zero_mask to turn the mantissa and exponent into zero if the input was zero. - * 6. Combine with the sign of the input number. - */ - return sign | (((nonsign << renorm_shift >> 3) + ((0x70 - renorm_shift) << 23)) & ~zero_mask); -} - -/* - * Convert a 16-bit floating-point number in ARM alternative half-precision format, in bit representation, to - * a 32-bit floating-point number in IEEE single-precision format. - * - * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals) - * floating-point operations and bitcasts between integer and floating-point variables. - */ -static inline float fp16_alt_to_fp32_value(uint16_t h) { - /* - * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word: - * +---+-----+------------+-------------------+ - * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| - * +---+-----+------------+-------------------+ - * Bits 31 26-30 16-25 0-15 - * - * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits. - */ - const uint32_t w = (uint32_t) h << 16; - /* - * Extract the sign of the input number into the high bit of the 32-bit word: - * - * +---+----------------------------------+ - * | S |0000000 00000000 00000000 00000000| - * +---+----------------------------------+ - * Bits 31 0-31 - */ - const uint32_t sign = w & UINT32_C(0x80000000); - /* - * Extract mantissa and biased exponent of the input number into the high bits of the 32-bit word: - * - * +-----+------------+---------------------+ - * |EEEEE|MM MMMM MMMM|0 0000 0000 0000 0000| - * +-----+------------+---------------------+ - * Bits 27-31 17-26 0-16 - */ - const uint32_t two_w = w + w; - - /* - * Shift mantissa and exponent into bits 23-28 and bits 13-22 so they become mantissa and exponent - * of a single-precision floating-point number: - * - * S|Exponent | Mantissa - * +-+---+-----+------------+----------------+ - * |0|000|EEEEE|MM MMMM MMMM|0 0000 0000 0000| - * +-+---+-----+------------+----------------+ - * Bits | 23-31 | 0-22 - * - * Next, the exponent is adjusted for the difference in exponent bias between single-precision and half-precision - * formats (0x7F - 0xF = 0x70). This operation never overflows or generates non-finite values, as the largest - * half-precision exponent is 0x1F and after the adjustment is can not exceed 0x8F < 0xFE (largest single-precision - * exponent for non-finite values). - * - * Note that this operation does not handle denormal inputs (where biased exponent == 0). However, they also do not - * operate on denormal inputs, and do not produce denormal results. - */ - const float exp_offset = UINT32_C(0x70) << 23; - const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset); - - /* - * Convert denormalized half-precision inputs into single-precision results (always normalized). - * Zero inputs are also handled here. - * - * In a denormalized number the biased exponent is zero, and mantissa has on-zero bits. - * First, we shift mantissa into bits 0-9 of the 32-bit word. - * - * zeros | mantissa - * +---------------------------+------------+ - * |0000 0000 0000 0000 0000 00|MM MMMM MMMM| - * +---------------------------+------------+ - * Bits 10-31 0-9 - * - * Now, remember that denormalized half-precision numbers are represented as: - * FP16 = mantissa * 2**(-24). - * The trick is to construct a normalized single-precision number with the same mantissa and thehalf-precision input - * and with an exponent which would scale the corresponding mantissa bits to 2**(-24). - * A normalized single-precision floating-point number is represented as: - * FP32 = (1 + mantissa * 2**(-23)) * 2**(exponent - 127) - * Therefore, when the biased exponent is 126, a unit change in the mantissa of the input denormalized half-precision - * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same ammount. - * - * The last step is to adjust the bias of the constructed single-precision number. When the input half-precision number - * is zero, the constructed single-precision number has the value of - * FP32 = 1 * 2**(126 - 127) = 2**(-1) = 0.5 - * Therefore, we need to subtract 0.5 from the constructed single-precision number to get the numerical equivalent of - * the input half-precision number. - */ - const uint32_t magic_mask = UINT32_C(126) << 23; - const float magic_bias = 0.5f; - const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; - - /* - * - Choose either results of conversion of input as a normalized number, or as a denormalized number, depending on the - * input exponent. The variable two_w contains input exponent in bits 27-31, therefore if its smaller than 2**27, the - * input is either a denormal number, or zero. - * - Combine the result of conversion of exponent and mantissa with the sign of the input number. - */ - const uint32_t denormalized_cutoff = UINT32_C(1) << 27; - const uint32_t result = sign | - (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value)); - return fp32_from_bits(result); -} - -/* - * Convert a 32-bit floating-point number in IEEE single-precision format to a 16-bit floating-point number in - * ARM alternative half-precision format, in bit representation. - * - * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals) - * floating-point operations and bitcasts between integer and floating-point variables. - */ -static inline uint16_t fp16_alt_from_fp32_value(float f) { - const uint32_t w = fp32_to_bits(f); - const uint32_t sign = w & UINT32_C(0x80000000); - const uint32_t shl1_w = w + w; - - const uint32_t shl1_max_fp16_fp32 = UINT32_C(0x8FFFC000); - const uint32_t shl1_base = shl1_w > shl1_max_fp16_fp32 ? shl1_max_fp16_fp32 : shl1_w; - uint32_t shl1_bias = shl1_base & UINT32_C(0xFF000000); - const uint32_t exp_difference = 23 - 10; - const uint32_t shl1_bias_min = (127 - 1 - exp_difference) << 24; - if (shl1_bias < shl1_bias_min) { - shl1_bias = shl1_bias_min; - } - - const float bias = fp32_from_bits((shl1_bias >> 1) + ((exp_difference + 2) << 23)); - const float base = fp32_from_bits((shl1_base >> 1) + (2 << 23)) + bias; - - const uint32_t exp_f = fp32_to_bits(base) >> 13; - return (sign >> 16) | ((exp_f & UINT32_C(0x00007C00)) + (fp32_to_bits(base) & UINT32_C(0x00000FFF))); -} - -#endif /* FP16_FP16_H */ diff --git a/Texture2DDecoderNative/pvrtc.cpp b/Texture2DDecoderNative/pvrtc.cpp deleted file mode 100644 index 9e4751f..0000000 --- a/Texture2DDecoderNative/pvrtc.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include "pvrtc.h" -#include -#include -#include "color.h" -#include "endianness.h" - -static const int PVRTC1_STANDARD_WEIGHT[] = {0, 3, 5, 8}; -static const int PVRTC1_PUNCHTHROUGH_WEIGHT[] = {0, 4, 4, 8}; - -static inline long morton_index(const long x, const long y, const long min_dim) { - long offset = 0, shift = 0; - for (long mask = 1; mask < min_dim; mask <<= 1, shift++) - offset |= (((y & mask) | ((x & mask) << 1))) << shift; - offset |= ((x | y) >> shift) << (shift * 2); - return offset; -} - -static void get_texel_colors(const uint8_t *data, PVRTCTexelInfo *info) { - uint16_t ca = lton16(*(uint16_t *)(data + 4)); - uint16_t cb = lton16(*(uint16_t *)(data + 6)); - if (ca & 0x8000) { - info->a.r = ca >> 10 & 0x1f; - info->a.g = ca >> 5 & 0x1f; - info->a.b = (ca & 0x1e) | (ca >> 4 & 1); - info->a.a = 0xf; - } else { - info->a.r = (ca >> 7 & 0x1e) | (ca >> 11 & 1); - info->a.g = (ca >> 3 & 0x1e) | (ca >> 7 & 1); - info->a.b = (ca << 1 & 0x1c) | (ca >> 2 & 3); - info->a.a = ca >> 11 & 0xe; - } - if (cb & 0x8000) { - info->b.r = cb >> 10 & 0x1f; - info->b.g = cb >> 5 & 0x1f; - info->b.b = cb & 0x1f; - info->b.a = 0xf; - } else { - info->b.r = (cb >> 7 & 0x1e) | (cb >> 11 & 1); - info->b.g = (cb >> 3 & 0x1e) | (cb >> 7 & 1); - info->b.b = (cb << 1 & 0x1e) | (cb >> 3 & 1); - info->b.a = cb >> 11 & 0xe; - } -} - -static void get_texel_weights_4bpp(const uint8_t *data, PVRTCTexelInfo *info) { - info->punch_through_flag = 0; - - int mod_mode = data[4] & 1; - uint32_t mod_bits = lton32(*(uint32_t *)data); - - if (mod_mode) { - for (int i = 0; i < 16; i++, mod_bits >>= 2) { - info->weight[i] = PVRTC1_PUNCHTHROUGH_WEIGHT[mod_bits & 3]; - if ((mod_bits & 3) == 2) - info->punch_through_flag |= 1 << i; - } - } else { - for (int i = 0; i < 16; i++, mod_bits >>= 2) - info->weight[i] = PVRTC1_STANDARD_WEIGHT[mod_bits & 3]; - } -} - -static void get_texel_weights_2bpp(const uint8_t *data, PVRTCTexelInfo *info) { - info->punch_through_flag = 0; - - int mod_mode = data[4] & 1; - uint32_t mod_bits = lton32(*(uint32_t *)data); - - if (mod_mode) { - int fillflag = data[0] & 1 ? (data[2] & 0x10 ? -1 : -2) : -3; - for (int y = 0, i = 1; y < 4; ++y & 1 ? --i : ++i) - for (int x = 0; x < 4; x++, i += 2) - info->weight[i] = fillflag; - for (int y = 0, i = 0; y < 4; ++y & 1 ? ++i : --i) - for (int x = 0; x < 4; x++, i += 2, mod_bits >>= 2) - info->weight[i] = PVRTC1_STANDARD_WEIGHT[mod_bits & 3]; - info->weight[0] = (info->weight[0] + 3) & 8; - if (data[0] & 1) - info->weight[20] = (info->weight[20] + 3) & 8; - } else { - for (int i = 0; i < 32; i++, mod_bits >>= 1) - info->weight[i] = mod_bits & 1 ? 8 : 0; - } -} - -static void applicate_color_4bpp(const uint8_t *data, PVRTCTexelInfo *const info[9], uint32_t buf[32]) { - static const int INTERP_WEIGHT[4][3] = {{2, 2, 0}, {1, 3, 0}, {0, 4, 0}, {0, 3, 1}}; - PVRTCTexelColorInt clr_a[16] = {}, clr_b[16] = {}; - - for (int y = 0, i = 0; y < 4; y++) { - for (int x = 0; x < 4; x++, i++) { - for (int acy = 0, ac = 0; acy < 3; acy++) { - for (int acx = 0; acx < 3; acx++, ac++) { - int interp_weight = INTERP_WEIGHT[x][acx] * INTERP_WEIGHT[y][acy]; - clr_a[i].r += info[ac]->a.r * interp_weight; - clr_a[i].g += info[ac]->a.g * interp_weight; - clr_a[i].b += info[ac]->a.b * interp_weight; - clr_a[i].a += info[ac]->a.a * interp_weight; - clr_b[i].r += info[ac]->b.r * interp_weight; - clr_b[i].g += info[ac]->b.g * interp_weight; - clr_b[i].b += info[ac]->b.b * interp_weight; - clr_b[i].a += info[ac]->b.a * interp_weight; - } - } - clr_a[i].r = (clr_a[i].r >> 1) + (clr_a[i].r >> 6); - clr_a[i].g = (clr_a[i].g >> 1) + (clr_a[i].g >> 6); - clr_a[i].b = (clr_a[i].b >> 1) + (clr_a[i].b >> 6); - clr_a[i].a = (clr_a[i].a) + (clr_a[i].a >> 4); - clr_b[i].r = (clr_b[i].r >> 1) + (clr_b[i].r >> 6); - clr_b[i].g = (clr_b[i].g >> 1) + (clr_b[i].g >> 6); - clr_b[i].b = (clr_b[i].b >> 1) + (clr_b[i].b >> 6); - clr_b[i].a = (clr_b[i].a) + (clr_b[i].a >> 4); - } - } - - const PVRTCTexelInfo *self_info = info[4]; - uint32_t punch_through_flag = self_info->punch_through_flag; - for (int i = 0; i < 16; i++, punch_through_flag >>= 1) { - buf[i] = color((clr_a[i].r * (8 - self_info->weight[i]) + clr_b[i].r * self_info->weight[i]) / 8, - (clr_a[i].g * (8 - self_info->weight[i]) + clr_b[i].g * self_info->weight[i]) / 8, - (clr_a[i].b * (8 - self_info->weight[i]) + clr_b[i].b * self_info->weight[i]) / 8, - punch_through_flag & 1 - ? 0 - : (clr_a[i].a * (8 - self_info->weight[i]) + clr_b[i].a * self_info->weight[i]) / 8); - } -} - -static void applicate_color_2bpp(const uint8_t *data, PVRTCTexelInfo *const info[9], uint32_t buf[32]) { - static const int INTERP_WEIGHT_X[8][3] = {{4, 4, 0}, {3, 5, 0}, {2, 6, 0}, {1, 7, 0}, - {0, 8, 0}, {0, 7, 1}, {0, 6, 2}, {0, 5, 3}}; - static const int INTERP_WEIGHT_Y[4][3] = {{2, 2, 0}, {1, 3, 0}, {0, 4, 0}, {0, 3, 1}}; - PVRTCTexelColorInt clr_a[32] = {}, clr_b[32] = {}; - - for (int y = 0, i = 0; y < 4; y++) { - for (int x = 0; x < 8; x++, i++) { - for (int acy = 0, ac = 0; acy < 3; acy++) { - for (int acx = 0; acx < 3; acx++, ac++) { - int interp_weight = INTERP_WEIGHT_X[x][acx] * INTERP_WEIGHT_Y[y][acy]; - clr_a[i].r += info[ac]->a.r * interp_weight; - clr_a[i].g += info[ac]->a.g * interp_weight; - clr_a[i].b += info[ac]->a.b * interp_weight; - clr_a[i].a += info[ac]->a.a * interp_weight; - clr_b[i].r += info[ac]->b.r * interp_weight; - clr_b[i].g += info[ac]->b.g * interp_weight; - clr_b[i].b += info[ac]->b.b * interp_weight; - clr_b[i].a += info[ac]->b.a * interp_weight; - } - } - clr_a[i].r = (clr_a[i].r >> 2) + (clr_a[i].r >> 7); - clr_a[i].g = (clr_a[i].g >> 2) + (clr_a[i].g >> 7); - clr_a[i].b = (clr_a[i].b >> 2) + (clr_a[i].b >> 7); - clr_a[i].a = (clr_a[i].a >> 1) + (clr_a[i].a >> 5); - clr_b[i].r = (clr_b[i].r >> 2) + (clr_b[i].r >> 7); - clr_b[i].g = (clr_b[i].g >> 2) + (clr_b[i].g >> 7); - clr_b[i].b = (clr_b[i].b >> 2) + (clr_b[i].b >> 7); - clr_b[i].a = (clr_b[i].a >> 1) + (clr_b[i].a >> 5); - } - } - - static const int POSYA[4][2] = {{1, 24}, {4, -8}, {4, -8}, {4, -8}}; - static const int POSYB[4][2] = {{4, 8}, {4, 8}, {4, 8}, {7, -24}}; - static const int POSXL[8][2] = {{3, 7}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}}; - static const int POSXR[8][2] = {{4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {5, -7}}; - - PVRTCTexelInfo *self_info = info[4]; - uint32_t punch_through_flag = self_info->punch_through_flag; - for (int y = 0, i = 0; y < 4; y++) { - for (int x = 0; x < 8; x++, i++, punch_through_flag >>= 1) { - switch (self_info->weight[i]) { - case -1: - self_info->weight[i] = - (info[POSYA[y][0]]->weight[i + POSYA[y][1]] + info[POSYB[y][0]]->weight[i + POSYB[y][1]] + 1) / 2; - break; - case -2: - self_info->weight[i] = - (info[POSXL[x][0]]->weight[i + POSXL[x][1]] + info[POSXR[x][0]]->weight[i + POSXR[x][1]] + 1) / 2; - break; - case -3: - self_info->weight[i] = - (info[POSYA[y][0]]->weight[i + POSYA[y][1]] + info[POSYB[y][0]]->weight[i + POSYB[y][1]] + - info[POSXL[x][0]]->weight[i + POSXL[x][1]] + info[POSXR[x][0]]->weight[i + POSXR[x][1]] + 2) / - 4; - break; - } - buf[i] = color((clr_a[i].r * (8 - self_info->weight[i]) + clr_b[i].r * self_info->weight[i]) / 8, - (clr_a[i].g * (8 - self_info->weight[i]) + clr_b[i].g * self_info->weight[i]) / 8, - (clr_a[i].b * (8 - self_info->weight[i]) + clr_b[i].b * self_info->weight[i]) / 8, - punch_through_flag & 1 - ? 0 - : (clr_a[i].a * (8 - self_info->weight[i]) + clr_b[i].a * self_info->weight[i]) / 8); - } - } -} - -int decode_pvrtc(const uint8_t *data, const long w, const long h, uint32_t *image, const int is2bpp) { - long bw = is2bpp ? 8 : 4; - long num_blocks_x = is2bpp ? (w + 7) / 8 : (w + 3) / 4; - long num_blocks_y = (h + 3) / 4; - long num_blocks = num_blocks_x * num_blocks_y; - long min_num_blocks = num_blocks_x <= num_blocks_y ? num_blocks_x : num_blocks_y; - - if ((num_blocks_x & (num_blocks_x - 1)) || (num_blocks_y & (num_blocks_y - 1))) { - //extern const char* error_msg; - //error_msg = "the number of blocks of each side must be a power of 2"; - return 0; - } - - PVRTCTexelInfo *texel_info = (PVRTCTexelInfo *)malloc(sizeof(PVRTCTexelInfo) * num_blocks); - if (texel_info == NULL) { - //extern const char* error_msg; - //error_msg = "memory allocation failed"; - return 0; - } - - void (*get_texel_weights_func)(const uint8_t *, PVRTCTexelInfo *) = - is2bpp ? get_texel_weights_2bpp : get_texel_weights_4bpp; - void (*applicate_color_func)(const uint8_t *, PVRTCTexelInfo *const[9], uint32_t[32]) = - is2bpp ? applicate_color_2bpp : applicate_color_4bpp; - - const uint8_t *d = data; - for (long i = 0; i < num_blocks; i++, d += 8) { - get_texel_colors(d, &texel_info[i]); - get_texel_weights_func(d, &texel_info[i]); - } - - uint32_t buffer[32]; - PVRTCTexelInfo *local_info[9]; - long pos_x[3], pos_y[3]; - - for (long by = 0; by < num_blocks_y; by++) { - pos_y[0] = by == 0 ? num_blocks_y - 1 : by - 1; - pos_y[1] = by; - pos_y[2] = by == num_blocks_y - 1 ? 0 : by + 1; - for (long bx = 0, x = 0; bx < num_blocks_x; bx++, x += 4) { - pos_x[0] = bx == 0 ? num_blocks_x - 1 : bx - 1; - pos_x[1] = bx; - pos_x[2] = bx == num_blocks_x - 1 ? 0 : bx + 1; - for (long cy = 0, c = 0; cy < 3; cy++) - for (long cx = 0; cx < 3; cx++, c++) - local_info[c] = &texel_info[morton_index(pos_x[cx], pos_y[cy], min_num_blocks)]; - applicate_color_func(data + morton_index(bx, by, min_num_blocks) * 8, local_info, buffer); - copy_block_buffer(bx, by, w, h, bw, 4, buffer, image); - } - } - - free(texel_info); - return 1; -} diff --git a/Texture2DDecoderNative/pvrtc.h b/Texture2DDecoderNative/pvrtc.h deleted file mode 100644 index f0a7e60..0000000 --- a/Texture2DDecoderNative/pvrtc.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef PVRTC_H -#define PVRTC_H - -#include - -typedef struct { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; -} PVRTCTexelColor; - -typedef struct { - int r; - int g; - int b; - int a; -} PVRTCTexelColorInt; - -typedef struct { - PVRTCTexelColor a; - PVRTCTexelColor b; - int8_t weight[32]; - uint32_t punch_through_flag; -} PVRTCTexelInfo; - -int decode_pvrtc(const uint8_t *, const long, const long, uint32_t *, const int); - -#endif /* end of include guard: PVRTC_H */ diff --git a/Texture2DDecoderNative/resource.h b/Texture2DDecoderNative/resource.h deleted file mode 100644 index 9345558..0000000 --- a/Texture2DDecoderNative/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Texture2DDecoderNative.rc - -// ¶һĬֵ -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Texture2DDecoderNative/unitycrunch.cpp b/Texture2DDecoderNative/unitycrunch.cpp deleted file mode 100644 index 9e6d658..0000000 --- a/Texture2DDecoderNative/unitycrunch.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "unitycrunch.h" -#include -#include -#include "unitycrunch/crn_decomp.h" - -bool unity_crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size) { - unitycrnd::crn_texture_info tex_info; - if (!unitycrnd::crnd_get_texture_info(data, data_size, &tex_info)) - { - return false; - } - - unitycrnd::crnd_unpack_context pContext = unitycrnd::crnd_unpack_begin(data, data_size); - if (!pContext) - { - return false; - } - - const crn_uint32 width = std::max(1U, tex_info.m_width >> level_index); - const crn_uint32 height = std::max(1U, tex_info.m_height >> level_index); - const crn_uint32 blocks_x = std::max(1U, (width + 3) >> 2); - const crn_uint32 blocks_y = std::max(1U, (height + 3) >> 2); - const crn_uint32 row_pitch = blocks_x * unitycrnd::crnd_get_bytes_per_dxt_block(tex_info.m_format); - const crn_uint32 total_face_size = row_pitch * blocks_y; - *ret = new uint8_t[total_face_size]; - *ret_size = total_face_size; - if (!unitycrnd::crnd_unpack_level(pContext, ret, total_face_size, row_pitch, level_index)) - { - unitycrnd::crnd_unpack_end(pContext); - return false; - } - unitycrnd::crnd_unpack_end(pContext); - return true; -} \ No newline at end of file diff --git a/Texture2DDecoderNative/unitycrunch.h b/Texture2DDecoderNative/unitycrunch.h deleted file mode 100644 index dd26ac6..0000000 --- a/Texture2DDecoderNative/unitycrunch.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -bool unity_crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size); \ No newline at end of file diff --git a/Texture2DDecoderNative/unitycrunch/crn_decomp.h b/Texture2DDecoderNative/unitycrunch/crn_decomp.h deleted file mode 100644 index e38a143..0000000 --- a/Texture2DDecoderNative/unitycrunch/crn_decomp.h +++ /dev/null @@ -1,3821 +0,0 @@ -// File: crn_decomp.h - Fast CRN->DXTc texture transcoder header file library -// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC -// See Copyright Notice and license at the end of this file. -// -// This single header file contains *all* of the code necessary to unpack .CRN files to raw DXTn bits. -// It does NOT depend on the crn compression library. -// -// Note: This is a single file, stand-alone C++ library which is controlled by the use of the following macro: -// If CRND_INCLUDE_CRND_H is NOT defined, the header is included. -// -// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing -#ifndef CRND_INCLUDE_CRND_H -#define CRND_INCLUDE_CRND_H - -// Include crn_defs.h (only to bring in some basic CRN-related types and structures). -#include "crn_defs.h" - -#include -#include -#ifdef _WIN32 -#include -#else -#include -#endif -#include -#include // needed for placement new, _msize, _expand - -#define CRND_RESTRICT __restrict - -#ifdef _MSC_VER -#pragma warning(disable : 4127) // warning C4127: conditional expression is constant -#endif - -#ifdef CRND_DEVEL -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x500 -#endif -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef -#define NOMINMAX -#endif -#include "windows.h" // only for IsDebuggerPresent(), DebugBreak(), and OutputDebugStringA() -#endif - -// File: crnd_types.h -namespace unitycrnd { -const crn_uint8 cUINT8_MIN = 0; -const crn_uint8 cUINT8_MAX = 0xFFU; -const uint16 cUINT16_MIN = 0; -const uint16 cUINT16_MAX = 0xFFFFU; -const uint32 cUINT32_MIN = 0; -const uint32 cUINT32_MAX = 0xFFFFFFFFU; - -const int8 cINT8_MIN = -128; -const int8 cINT8_MAX = 127; -const int16 cINT16_MIN = -32768; -const int16 cINT16_MAX = 32767; -const int32 cINT32_MIN = (-2147483647 - 1); -const int32 cINT32_MAX = 2147483647; - -enum eClear { cClear }; - -const uint32 cIntBits = 32U; - -template -struct int_traits { - enum { cMin = unitycrnd::cINT32_MIN, - cMax = unitycrnd::cINT32_MAX, - cSigned = true }; -}; - -template <> -struct int_traits { - enum { cMin = unitycrnd::cINT8_MIN, - cMax = unitycrnd::cINT8_MAX, - cSigned = true }; -}; -template <> -struct int_traits { - enum { cMin = unitycrnd::cINT16_MIN, - cMax = unitycrnd::cINT16_MAX, - cSigned = true }; -}; -template <> -struct int_traits { - enum { cMin = unitycrnd::cINT32_MIN, - cMax = unitycrnd::cINT32_MAX, - cSigned = true }; -}; - -template <> -struct int_traits { - enum { cMin = 0, - cMax = unitycrnd::cUINT8_MAX, - cSigned = false }; -}; -template <> -struct int_traits { - enum { cMin = 0, - cMax = unitycrnd::cUINT16_MAX, - cSigned = false }; -}; -template <> -struct int_traits { - enum { cMin = 0, - cMax = unitycrnd::cUINT32_MAX, - cSigned = false }; -}; - -struct empty_type {}; - -} // namespace unitycrnd - -// File: crnd_platform.h -namespace unitycrnd { - -bool crnd_is_debugger_present(); -void crnd_debug_break(); -void crnd_output_debug_string(const char* p); - -// actually in crnd_assert.cpp -void crnd_assert(const char* pExp, const char* pFile, unsigned line); -void crnd_fail(const char* pExp, const char* pFile, unsigned line); - -} // namespace unitycrnd - -// File: crnd_assert.h -namespace unitycrnd { -void crnd_assert(const char* pExp, const char* pFile, unsigned line); - -#ifdef NDEBUG -#define CRND_ASSERT(x) ((void)0) -#undef CRND_ASSERTS_ENABLED -#else -#define CRND_ASSERT(_exp) (void)((!!(_exp)) || (unitycrnd::crnd_assert(#_exp, __FILE__, __LINE__), 0)) -#define CRND_ASSERTS_ENABLED -#endif - -void crnd_trace(const char* pFmt, va_list args); -void crnd_trace(const char* pFmt, ...); - -} // namespace unitycrnd - -// File: crnd_helpers.h -namespace unitycrnd { -namespace helpers { -template -struct rel_ops { - friend bool operator!=(const T& x, const T& y) { return (!(x == y)); } - friend bool operator>(const T& x, const T& y) { return (y < x); } - friend bool operator<=(const T& x, const T& y) { return (!(y < x)); } - friend bool operator>=(const T& x, const T& y) { return (!(x < y)); } -}; - -template -inline T* construct(T* p) { - return new (static_cast(p)) T; -} - -template -inline T* construct(T* p, const U& init) { - return new (static_cast(p)) T(init); -} - -template -void construct_array(T* p, uint32 n) { - T* q = p + n; - for (; p != q; ++p) - new (static_cast(p)) T; -} - -template -void construct_array(T* p, uint32 n, const U& init) { - T* q = p + n; - for (; p != q; ++p) - new (static_cast(p)) T(init); -} - -template -inline void destruct(T* p) { - p->~T(); -} - -template -inline void destruct_array(T* p, uint32 n) { - T* q = p + n; - for (; p != q; ++p) - p->~T(); -} - -} // namespace helpers - -} // namespace unitycrnd - -// File: crnd_traits.h -namespace unitycrnd { -template -struct scalar_type { - enum { cFlag = false }; - static inline void construct(T* p) { helpers::construct(p); } - static inline void construct(T* p, const T& init) { helpers::construct(p, init); } - static inline void construct_array(T* p, uint32 n) { helpers::construct_array(p, n); } - static inline void destruct(T* p) { helpers::destruct(p); } - static inline void destruct_array(T* p, uint32 n) { helpers::destruct_array(p, n); } -}; - -template -struct scalar_type { - enum { cFlag = true }; - static inline void construct(T** p) { memset(p, 0, sizeof(T*)); } - static inline void construct(T** p, T* init) { *p = init; } - static inline void construct_array(T** p, uint32 n) { memset(p, 0, sizeof(T*) * n); } - static inline void destruct(T**) {} - static inline void destruct_array(T**, uint32) {} -}; - -#define CRND_DEFINE_BUILT_IN_TYPE(X) \ - template <> \ - struct scalar_type { \ - enum { cFlag = true }; \ - static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \ - static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \ - static inline void construct_array(X* p, uint32 n) { memset(p, 0, sizeof(X) * n); } \ - static inline void destruct(X*) {} \ - static inline void destruct_array(X*, uint32) {} \ - }; - -CRND_DEFINE_BUILT_IN_TYPE(bool) -CRND_DEFINE_BUILT_IN_TYPE(char) -CRND_DEFINE_BUILT_IN_TYPE(unsigned char) -CRND_DEFINE_BUILT_IN_TYPE(short) -CRND_DEFINE_BUILT_IN_TYPE(unsigned short) -CRND_DEFINE_BUILT_IN_TYPE(int) -CRND_DEFINE_BUILT_IN_TYPE(unsigned int) -CRND_DEFINE_BUILT_IN_TYPE(long) -CRND_DEFINE_BUILT_IN_TYPE(unsigned long) -CRND_DEFINE_BUILT_IN_TYPE(int64) -CRND_DEFINE_BUILT_IN_TYPE(uint64) -CRND_DEFINE_BUILT_IN_TYPE(float) -CRND_DEFINE_BUILT_IN_TYPE(double) -CRND_DEFINE_BUILT_IN_TYPE(long double) - -#undef CRND_DEFINE_BUILT_IN_TYPE - -// See: http://erdani.org/publications/cuj-2004-06.pdf - -template -struct bitwise_movable { - enum { cFlag = false }; -}; - -// Defines type Q as bitwise movable. -#define CRND_DEFINE_BITWISE_MOVABLE(Q) \ - template <> \ - struct bitwise_movable { \ - enum { cFlag = true }; \ - }; - -// From yasli_traits.h: -// Credit goes to Boost; -// also found in the C++ Templates book by Vandevoorde and Josuttis - -typedef char (&yes_t)[1]; -typedef char (&no_t)[2]; - -template -yes_t class_test(int U::*); -template -no_t class_test(...); - -template -struct is_class { - enum { value = (sizeof(class_test(0)) == sizeof(yes_t)) }; -}; - -template -struct is_pointer { - enum { value = false }; -}; - -template -struct is_pointer { - enum { value = true }; -}; - -#define CRND_IS_POD(T) __is_pod(T) - -} // namespace unitycrnd - -// File: crnd_mem.h -namespace unitycrnd { -void* crnd_malloc(size_t size, size_t* pActual_size = NULL); -void* crnd_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true); -void crnd_free(void* p); -size_t crnd_msize(void* p); - -template -inline T* crnd_new() { - T* p = static_cast(crnd_malloc(sizeof(T))); - if (!p) - return NULL; - - return helpers::construct(p); -} - -template -inline T* crnd_new(const T& init) { - T* p = static_cast(crnd_malloc(sizeof(T))); - if (!p) - return NULL; - - return helpers::construct(p, init); -} - -template -inline T* crnd_new_array(uint32 num) { - if (!num) - num = 1; - - uint8* q = static_cast(crnd_malloc(CRND_MIN_ALLOC_ALIGNMENT + sizeof(T) * num)); - if (!q) - return NULL; - - T* p = reinterpret_cast(q + CRND_MIN_ALLOC_ALIGNMENT); - - reinterpret_cast(p)[-1] = num; - reinterpret_cast(p)[-2] = ~num; - - helpers::construct_array(p, num); - return p; -} - -template -inline void crnd_delete(T* p) { - if (p) { - helpers::destruct(p); - crnd_free(p); - } -} - -template -inline void crnd_delete_array(T* p) { - if (p) { - const uint32 num = reinterpret_cast(p)[-1]; - CRND_ASSERT(num && (num == ~reinterpret_cast(p)[-2])); - - helpers::destruct_array(p, num); - - crnd_free(reinterpret_cast(p) - CRND_MIN_ALLOC_ALIGNMENT); - } -} - -} // namespace unitycrnd - -// File: crnd_math.h -namespace unitycrnd { -namespace math { -const float cNearlyInfinite = 1.0e+37f; - -const float cDegToRad = 0.01745329252f; -const float cRadToDeg = 57.29577951f; - -extern uint32 g_bitmasks[32]; - -// Yes I know these should probably be pass by ref, not val: -// http://www.stepanovpapers.com/notes.pdf -// Just don't use them on non-simple (non built-in) types! -template -inline T minimum(T a, T b) { - return (a < b) ? a : b; -} - -template -inline T minimum(T a, T b, T c) { - return minimum(minimum(a, b), c); -} - -template -inline T maximum(T a, T b) { - return (a > b) ? a : b; -} - -template -inline T maximum(T a, T b, T c) { - return maximum(maximum(a, b), c); -} - -template -inline T clamp(T value, T low, T high) { - return (value < low) ? low : ((value > high) ? high : value); -} - -template -inline T square(T value) { - return value * value; -} - -inline bool is_power_of_2(uint32 x) { - return x && ((x & (x - 1U)) == 0U); -} - -// From "Hackers Delight" -inline int next_pow2(uint32 val) { - val--; - val |= val >> 16; - val |= val >> 8; - val |= val >> 4; - val |= val >> 2; - val |= val >> 1; - return val + 1; -} - -// Returns the total number of bits needed to encode v. -inline uint32 total_bits(uint32 v) { - uint32 l = 0; - while (v > 0U) { - v >>= 1; - l++; - } - return l; -} - -inline uint floor_log2i(uint v) { - uint l = 0; - while (v > 1U) { - v >>= 1; - l++; - } - return l; -} - -inline uint ceil_log2i(uint v) { - uint l = floor_log2i(v); - if ((l != cIntBits) && (v > (1U << l))) - l++; - return l; -} -} -} - -// File: crnd_utils.h -namespace unitycrnd { -namespace utils { -template -inline void zero_object(T& obj) { - memset(&obj, 0, sizeof(obj)); -} - -template -inline void zero_this(T* pObj) { - memset(pObj, 0, sizeof(*pObj)); -} - -template -inline void swap(T& left, T& right) { - T temp(left); - left = right; - right = temp; -} - -inline void invert_buf(void* pBuf, uint32 size) { - uint8* p = static_cast(pBuf); - - const uint32 half_size = size >> 1; - for (uint32 i = 0; i < half_size; i++) - swap(p[i], p[size - 1U - i]); -} - -static inline uint16 swap16(uint16 x) { - return static_cast((x << 8) | (x >> 8)); -} -static inline uint32 swap32(uint32 x) { - return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); -} - -uint32 compute_max_mips(uint32 width, uint32 height); - -} // namespace utils - -} // namespace unitycrnd - -// File: crnd_vector.h -namespace unitycrnd { -struct elemental_vector { - void* m_p; - uint32 m_size; - uint32 m_capacity; - - typedef void (*object_mover)(void* pDst, void* pSrc, uint32 num); - - bool increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pRelocate); -}; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4127) // warning C4127: conditional expression is constant -#endif - -template -class vector : public helpers::rel_ops > { - public: - typedef T* iterator; - typedef const T* const_iterator; - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - - inline vector() - : m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) { - } - - inline vector(const vector& other) - : m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) { - *this = other; - } - - inline vector(uint32 size) - : m_p(NULL), - m_size(0), - m_capacity(0), - m_alloc_failed(false) { - resize(size); - } - - inline ~vector() { - clear(); - } - - // I don't like this. Not at all. But exceptions, or just failing suck worse. - inline bool get_alloc_failed() const { return m_alloc_failed; } - inline void clear_alloc_failed() { m_alloc_failed = false; } - - inline bool assign(const vector& other) { - if (this == &other) - return true; - - if (m_capacity == other.m_size) - resize(0); - else { - clear(); - - if (!increase_capacity(other.m_size, false)) - return false; - } - - if (scalar_type::cFlag) - memcpy(m_p, other.m_p, other.m_size * sizeof(T)); - else { - T* pDst = m_p; - const T* pSrc = other.m_p; - for (uint32 i = other.m_size; i > 0; i--) - helpers::construct(pDst++, *pSrc++); - } - - m_size = other.m_size; - - return true; - } - - inline vector& operator=(const vector& other) { - assign(other); - return *this; - } - - inline const T* begin() const { return m_p; } - T* begin() { return m_p; } - - inline const T* end() const { return m_p + m_size; } - T* end() { return m_p + m_size; } - - inline bool empty() const { return !m_size; } - inline uint32 size() const { return m_size; } - inline uint32 capacity() const { return m_capacity; } - - inline const T& operator[](uint32 i) const { - CRND_ASSERT(i < m_size); - return m_p[i]; - } - inline T& operator[](uint32 i) { - CRND_ASSERT(i < m_size); - return m_p[i]; - } - - inline const T& front() const { - CRND_ASSERT(m_size); - return m_p[0]; - } - inline T& front() { - CRND_ASSERT(m_size); - return m_p[0]; - } - - inline const T& back() const { - CRND_ASSERT(m_size); - return m_p[m_size - 1]; - } - inline T& back() { - CRND_ASSERT(m_size); - return m_p[m_size - 1]; - } - - inline void clear() { - if (m_p) { - scalar_type::destruct_array(m_p, m_size); - crnd_free(m_p); - m_p = NULL; - m_size = 0; - m_capacity = 0; - } - - m_alloc_failed = false; - } - - inline bool reserve(uint32 new_capacity) { - if (!increase_capacity(new_capacity, false)) - return false; - - return true; - } - - inline bool resize(uint32 new_size) { - if (m_size != new_size) { - if (new_size < m_size) - scalar_type::destruct_array(m_p + new_size, m_size - new_size); - else { - if (new_size > m_capacity) { - if (!increase_capacity(new_size, new_size == (m_size + 1))) - return false; - } - - scalar_type::construct_array(m_p + m_size, new_size - m_size); - } - - m_size = new_size; - } - - return true; - } - - inline bool push_back(const T& obj) { - CRND_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size))); - - if (m_size >= m_capacity) { - if (!increase_capacity(m_size + 1, true)) - return false; - } - - scalar_type::construct(m_p + m_size, obj); - m_size++; - - return true; - } - - inline void pop_back() { - CRND_ASSERT(m_size); - - if (m_size) { - m_size--; - scalar_type::destruct(&m_p[m_size]); - } - } - - inline void insert(uint32 index, const T* p, uint32 n) { - CRND_ASSERT(index <= m_size); - if (!n) - return; - - const uint32 orig_size = m_size; - resize(m_size + n); - - const T* pSrc = m_p + orig_size - 1; - T* pDst = const_cast(pSrc) + n; - - const uint32 num_to_move = orig_size - index; - - for (uint32 i = 0; i < num_to_move; i++) { - CRND_ASSERT((pDst - m_p) < (int)m_size); - *pDst-- = *pSrc--; - } - - pSrc = p; - pDst = m_p + index; - - for (uint32 i = 0; i < n; i++) { - CRND_ASSERT((pDst - m_p) < (int)m_size); - *pDst++ = *p++; - } - } - - inline void erase(uint32 start, uint32 n) { - CRND_ASSERT((start + n) <= m_size); - - if (!n) - return; - - const uint32 num_to_move = m_size - (start + n); - - T* pDst = m_p + start; - T* pDst_end = pDst + num_to_move; - const T* pSrc = m_p + start + n; - - while (pDst != pDst_end) - *pDst++ = *pSrc++; - - scalar_type::destruct_array(pDst_end, n); - - m_size -= n; - } - - inline void erase(uint32 index) { - erase(index, 1); - } - - inline void erase(T* p) { - CRND_ASSERT((p >= m_p) && (p < (m_p + m_size))); - erase(p - m_p); - } - - inline bool operator==(const vector& rhs) const { - if (m_size != rhs.m_size) - return false; - else if (m_size) { - if (scalar_type::cFlag) - return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0; - else { - const T* pSrc = m_p; - const T* pDst = rhs.m_p; - for (uint32 i = m_size; i; i--) - if (!(*pSrc++ == *pDst++)) - return false; - } - } - - return true; - } - - inline bool operator<(const vector& rhs) const { - const uint32 min_size = math::minimum(m_size, rhs.m_size); - - const T* pSrc = m_p; - const T* pSrc_end = m_p + min_size; - const T* pDst = rhs.m_p; - - while ((pSrc < pSrc_end) && (*pSrc == *pDst)) { - pSrc++; - pDst++; - } - - if (pSrc < pSrc_end) - return *pSrc < *pDst; - - return m_size < rhs.m_size; - } - - void swap(vector& other) { - utils::swap(m_p, other.m_p); - utils::swap(m_size, other.m_size); - utils::swap(m_capacity, other.m_capacity); - } - - private: - T* m_p; - uint32 m_size; - uint32 m_capacity; - bool m_alloc_failed; - - template - struct is_vector { - enum { cFlag = false }; - }; - template - struct is_vector > { - enum { cFlag = true }; - }; - - static void object_mover(void* pDst_void, void* pSrc_void, uint32 num) { - T* pSrc = static_cast(pSrc_void); - T* const pSrc_end = pSrc + num; - T* pDst = static_cast(pDst_void); - - while (pSrc != pSrc_end) { - helpers::construct(pDst, *pSrc); - pSrc->~T(); - pSrc++; - pDst++; - } - } - - inline bool increase_capacity(uint32 min_new_capacity, bool grow_hint) { - if (!reinterpret_cast(this)->increase_capacity( - min_new_capacity, grow_hint, sizeof(T), - ((scalar_type::cFlag) || (is_vector::cFlag) || (bitwise_movable::cFlag) || CRND_IS_POD(T)) ? NULL : object_mover)) { - m_alloc_failed = true; - return false; - } - return true; - } -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -extern void vector_test(); - -} // namespace unitycrnd - -// File: crnd_private.h -namespace unitycrnd { -const crn_header* crnd_get_header(const void* pData, uint32 data_size); - -} // namespace unitycrnd - -// File: checksum.h -namespace unitycrnd { -// crc16() intended for small buffers - doesn't use an acceleration table. -const uint16 cInitCRC16 = 0; -uint16 crc16(const void* pBuf, uint32 len, uint16 crc = cInitCRC16); - -} // namespace unitycrnd - -// File: crnd_color.h -namespace unitycrnd { -template -struct color_quad_component_traits { - enum { - cSigned = false, - cFloat = false, - cMin = cUINT8_MIN, - cMax = cUINT8_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = true, - cFloat = false, - cMin = cINT16_MIN, - cMax = cINT16_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = false, - cFloat = false, - cMin = cUINT16_MIN, - cMax = cUINT16_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = true, - cFloat = false, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = false, - cFloat = false, - cMin = cUINT32_MIN, - cMax = cUINT32_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = false, - cFloat = true, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; -}; - -template <> -struct color_quad_component_traits { - enum { - cSigned = false, - cFloat = true, - cMin = cINT32_MIN, - cMax = cINT32_MAX - }; -}; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union -#pragma warning(disable : 4127) // warning C4127: conditional expression is constant -#endif - -template -class color_quad : public helpers::rel_ops > { - static parameter_type clamp(parameter_type v) { - if (component_traits::cFloat) - return v; - else { - if (v < component_traits::cMin) - return component_traits::cMin; - else if (v > component_traits::cMax) - return component_traits::cMax; - return v; - } - } - - public: - typedef component_type component_t; - typedef parameter_type parameter_t; - typedef color_quad_component_traits component_traits; - - enum { cNumComps = 4 }; - - union { - struct - { - component_type r; - component_type g; - component_type b; - component_type a; - }; - - component_type c[cNumComps]; - }; - - inline color_quad() { - } - - inline color_quad(eClear) - : r(0), g(0), b(0), a(0) { - } - - inline color_quad(const color_quad& other) - : r(other.r), g(other.g), b(other.b), a(other.a) { - } - - inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax) { - set(y, alpha); - } - - inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) { - set(red, green, blue, alpha); - } - - template - inline color_quad(const color_quad& other) - : r(clamp(other.r)), g(clamp(other.g)), b(clamp(other.b)), a(clamp(other.a)) { - } - - inline void clear() { - r = 0; - g = 0; - b = 0; - a = 0; - } - - inline color_quad& operator=(const color_quad& other) { - r = other.r; - g = other.g; - b = other.b; - a = other.a; - return *this; - } - - template - inline color_quad& operator=(const color_quad& other) { - r = clamp(other.r); - g = clamp(other.g); - b = clamp(other.b); - a = clamp(other.a); - return *this; - } - - inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax) { - y = clamp(y); - r = static_cast(y); - g = static_cast(y); - b = static_cast(y); - a = static_cast(alpha); - return *this; - } - - inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) { - r = static_cast(clamp(red)); - g = static_cast(clamp(green)); - b = static_cast(clamp(blue)); - a = static_cast(clamp(alpha)); - return *this; - } - - inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha) { - r = static_cast(red); - g = static_cast(green); - b = static_cast(blue); - a = static_cast(alpha); - return *this; - } - - inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue) { - r = static_cast(red); - g = static_cast(green); - b = static_cast(blue); - return *this; - } - - static inline parameter_type get_min_comp() { return component_traits::cMin; } - static inline parameter_type get_max_comp() { return component_traits::cMax; } - static inline bool get_comps_are_signed() { return component_traits::cSigned; } - - inline component_type operator[](uint32 i) const { - CRND_ASSERT(i < cNumComps); - return c[i]; - } - inline component_type& operator[](uint32 i) { - CRND_ASSERT(i < cNumComps); - return c[i]; - } - - inline color_quad& set_component(uint32 i, parameter_type f) { - CRND_ASSERT(i < cNumComps); - - c[i] = static_cast(clamp(f)); - - return *this; - } - - inline color_quad& clamp(const color_quad& l, const color_quad& h) { - for (uint32 i = 0; i < cNumComps; i++) - c[i] = static_cast(math::clamp(c[i], l[i], h[i])); - return *this; - } - - inline color_quad& clamp(parameter_type l, parameter_type h) { - for (uint32 i = 0; i < cNumComps; i++) - c[i] = static_cast(math::clamp(c[i], l, h)); - return *this; - } - - // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y). - inline parameter_type get_luma() const { - return static_cast((19595U * r + 38470U * g + 7471U * b + 32768) >> 16U); - } - - // Returns REC 709 luma. - inline parameter_type get_luma_rec709() const { - return static_cast((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U); - } - - inline uint32 squared_distance(const color_quad& c, bool alpha = true) const { - return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0); - } - - inline bool rgb_equals(const color_quad& rhs) const { - return (r == rhs.r) && (g == rhs.g) && (b == rhs.b); - } - - inline bool operator==(const color_quad& rhs) const { - return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a); - } - - inline bool operator<(const color_quad& rhs) const { - for (uint32 i = 0; i < cNumComps; i++) { - if (c[i] < rhs.c[i]) - return true; - else if (!(c[i] == rhs.c[i])) - return false; - } - return false; - } - - inline color_quad& operator+=(const color_quad& other) { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] + other.c[i])); - return *this; - } - - inline color_quad& operator-=(const color_quad& other) { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] - other.c[i])); - return *this; - } - - inline color_quad& operator*=(parameter_type v) { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(clamp(c[i] * v)); - return *this; - } - - inline color_quad& operator/=(parameter_type v) { - for (uint32 i = 0; i < 4; i++) - c[i] = static_cast(c[i] / v); - return *this; - } - - inline color_quad get_swizzled(uint32 x, uint32 y, uint32 z, uint32 w) const { - CRND_ASSERT((x | y | z | w) < 4); - return color_quad(c[x], c[y], c[z], c[w]); - } - - inline friend color_quad operator+(const color_quad& lhs, const color_quad& rhs) { - color_quad result(lhs); - result += rhs; - return result; - } - - inline friend color_quad operator-(const color_quad& lhs, const color_quad& rhs) { - color_quad result(lhs); - result -= rhs; - return result; - } - - inline friend color_quad operator*(const color_quad& lhs, parameter_type v) { - color_quad result(lhs); - result *= v; - return result; - } - - friend inline color_quad operator/(const color_quad& lhs, parameter_type v) { - color_quad result(lhs); - result /= v; - return result; - } - - friend inline color_quad operator*(parameter_type v, const color_quad& rhs) { - color_quad result(rhs); - result *= v; - return result; - } - - inline uint32 get_min_component_index(bool alpha = true) const { - uint32 index = 0; - uint32 limit = alpha ? cNumComps : (cNumComps - 1); - for (uint32 i = 1; i < limit; i++) - if (c[i] < c[index]) - index = i; - return index; - } - - inline uint32 get_max_component_index(bool alpha = true) const { - uint32 index = 0; - uint32 limit = alpha ? cNumComps : (cNumComps - 1); - for (uint32 i = 1; i < limit; i++) - if (c[i] > c[index]) - index = i; - return index; - } - - inline void get_float4(float* pDst) { - for (uint32 i = 0; i < 4; i++) - pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin); - } - - inline void get_float3(float* pDst) { - for (uint32 i = 0; i < 3; i++) - pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin); - } - - static inline color_quad make_black() { - return color_quad(0, 0, 0, component_traits::cMax); - } - - static inline color_quad make_white() { - return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax); - } -}; // class color_quad - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -template -struct scalar_type > { - enum { cFlag = true }; - static inline void construct(color_quad* p) {} - static inline void construct(color_quad* p, const color_quad& init) { memcpy(p, &init, sizeof(color_quad)); } - static inline void construct_array(color_quad* p, uint32 n) { p, n; } - static inline void destruct(color_quad* p) { p; } - static inline void destruct_array(color_quad* p, uint32 n) { p, n; } -}; - -typedef color_quad color_quad_u8; -typedef color_quad color_quad_i16; -typedef color_quad color_quad_u16; -typedef color_quad color_quad_i32; -typedef color_quad color_quad_u32; -typedef color_quad color_quad_f; -typedef color_quad color_quad_d; - -} // namespace unitycrnd - -// File: crnd_dxt.h -namespace unitycrnd { -enum dxt_format { - cDXTInvalid = -1, - - // cDXT1/1A must appear first! - cDXT1, - cDXT1A, - - cDXT3, - cDXT5, - cDXT5A, - - cDXN_XY, // inverted relative to standard ATI2, 360's DXN - cDXN_YX // standard ATI2 -}; - -enum dxt_constants { - cDXTBlockShift = 2U, - cDXTBlockSize = 1U << cDXTBlockShift, - - cDXT1BytesPerBlock = 8U, - cDXT5NBytesPerBlock = 16U, - - cDXT1SelectorBits = 2U, - cDXT1SelectorValues = 1U << cDXT1SelectorBits, - cDXT1SelectorMask = cDXT1SelectorValues - 1U, - - cDXT5SelectorBits = 3U, - cDXT5SelectorValues = 1U << cDXT5SelectorBits, - cDXT5SelectorMask = cDXT5SelectorValues - 1U -}; - -const float cDXT1MaxLinearValue = 3.0f; -const float cDXT1InvMaxLinearValue = 1.0f / 3.0f; - -const float cDXT5MaxLinearValue = 7.0f; -const float cDXT5InvMaxLinearValue = 1.0f / 7.0f; - -// Converts DXT1 raw color selector index to a linear value. -extern const uint8 g_dxt1_to_linear[cDXT1SelectorValues]; - -// Converts DXT5 raw alpha selector index to a linear value. -extern const uint8 g_dxt5_to_linear[cDXT5SelectorValues]; - -// Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear). -extern const uint8 g_dxt1_from_linear[cDXT1SelectorValues]; - -// Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear). -extern const uint8 g_dxt5_from_linear[cDXT5SelectorValues]; - -extern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues]; -extern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues]; - -struct dxt1_block { - uint8 m_low_color[2]; - uint8 m_high_color[2]; - - enum { cNumSelectorBytes = 4 }; - uint8 m_selectors[cNumSelectorBytes]; - - inline void clear() { - utils::zero_this(this); - } - - // These methods assume the in-memory rep is in LE byte order. - inline uint32 get_low_color() const { - return m_low_color[0] | (m_low_color[1] << 8U); - } - - inline uint32 get_high_color() const { - return m_high_color[0] | (m_high_color[1] << 8U); - } - - inline void set_low_color(uint16 c) { - m_low_color[0] = static_cast(c & 0xFF); - m_low_color[1] = static_cast((c >> 8) & 0xFF); - } - - inline void set_high_color(uint16 c) { - m_high_color[0] = static_cast(c & 0xFF); - m_high_color[1] = static_cast((c >> 8) & 0xFF); - } - - inline uint32 get_selector(uint32 x, uint32 y) const { - CRND_ASSERT((x < 4U) && (y < 4U)); - return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; - } - - inline void set_selector(uint32 x, uint32 y, uint32 val) { - CRND_ASSERT((x < 4U) && (y < 4U) && (val < 4U)); - - m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); - m_selectors[y] |= (val << (x * cDXT1SelectorBits)); - } - - static uint16 pack_color(const color_quad_u8& color, bool scaled, uint32 bias = 127U); - static uint16 pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias = 127U); - - static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint32 alpha = 255U); - static void unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled); - - static uint32 get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1); - static uint32 get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1); - // pDst must point to an array at least cDXT1SelectorValues long. - static uint32 get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1); - - static color_quad_u8 unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha = 255U); - static uint32 pack_endpoints(uint32 lo, uint32 hi); -}; - -CRND_DEFINE_BITWISE_MOVABLE(dxt1_block); - -struct dxt3_block { - enum { cNumAlphaBytes = 8 }; - uint8 m_alpha[cNumAlphaBytes]; - - void set_alpha(uint32 x, uint32 y, uint32 value, bool scaled); - uint32 get_alpha(uint32 x, uint32 y, bool scaled) const; -}; - -CRND_DEFINE_BITWISE_MOVABLE(dxt3_block); - -struct dxt5_block { - uint8 m_endpoints[2]; - - enum { cNumSelectorBytes = 6 }; - uint8 m_selectors[cNumSelectorBytes]; - - inline void clear() { - utils::zero_this(this); - } - - inline uint32 get_low_alpha() const { - return m_endpoints[0]; - } - - inline uint32 get_high_alpha() const { - return m_endpoints[1]; - } - - inline void set_low_alpha(uint32 i) { - CRND_ASSERT(i <= cUINT8_MAX); - m_endpoints[0] = static_cast(i); - } - - inline void set_high_alpha(uint32 i) { - CRND_ASSERT(i <= cUINT8_MAX); - m_endpoints[1] = static_cast(i); - } - - uint32 get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); } - - uint32 get_selectors_as_word(uint32 index) { - CRND_ASSERT(index < 3); - return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); - } - - inline uint32 get_selector(uint32 x, uint32 y) const { - CRND_ASSERT((x < 4U) && (y < 4U)); - - uint32 selector_index = (y * 4) + x; - uint32 bit_index = selector_index * cDXT5SelectorBits; - - uint32 byte_index = bit_index >> 3; - uint32 bit_ofs = bit_index & 7; - - uint32 v = m_selectors[byte_index]; - if (byte_index < (cNumSelectorBytes - 1)) - v |= (m_selectors[byte_index + 1] << 8); - - return (v >> bit_ofs) & 7; - } - - inline void set_selector(uint32 x, uint32 y, uint32 val) { - CRND_ASSERT((x < 4U) && (y < 4U) && (val < 8U)); - - uint32 selector_index = (y * 4) + x; - uint32 bit_index = selector_index * cDXT5SelectorBits; - - uint32 byte_index = bit_index >> 3; - uint32 bit_ofs = bit_index & 7; - - uint32 v = m_selectors[byte_index]; - if (byte_index < (cNumSelectorBytes - 1)) - v |= (m_selectors[byte_index + 1] << 8); - - v &= (~(7 << bit_ofs)); - v |= (val << bit_ofs); - - m_selectors[byte_index] = static_cast(v); - if (byte_index < (cNumSelectorBytes - 1)) - m_selectors[byte_index + 1] = static_cast(v >> 8); - } - - // Results written to alpha channel. - static uint32 get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h); - static uint32 get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h); - static uint32 get_block_values(color_quad_u8* pDst, uint32 l, uint32 h); - - static uint32 get_block_values6(uint32* pDst, uint32 l, uint32 h); - static uint32 get_block_values8(uint32* pDst, uint32 l, uint32 h); - // pDst must point to an array at least cDXT5SelectorValues long. - static uint32 get_block_values(uint32* pDst, uint32 l, uint32 h); - - static uint32 unpack_endpoint(uint32 packed, uint32 index); - static uint32 pack_endpoints(uint32 lo, uint32 hi); -}; - -CRND_DEFINE_BITWISE_MOVABLE(dxt5_block); - -} // namespace unitycrnd - -// File: crnd_prefix_coding.h -#ifdef _XBOX -#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 1 -#else -#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 0 -#endif - -namespace unitycrnd { -namespace prefix_coding { -const uint32 cMaxExpectedCodeSize = 16; -const uint32 cMaxSupportedSyms = 8192; -const uint32 cMaxTableBits = 11; - -class decoder_tables { - public: - inline decoder_tables() - : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) { - } - - inline decoder_tables(const decoder_tables& other) - : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) { - *this = other; - } - - decoder_tables& operator=(const decoder_tables& other) { - if (this == &other) - return *this; - - clear(); - - memcpy(this, &other, sizeof(*this)); - - if (other.m_lookup) { - m_lookup = crnd_new_array(m_cur_lookup_size); - if (m_lookup) - memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size); - } - - if (other.m_sorted_symbol_order) { - m_sorted_symbol_order = crnd_new_array(m_cur_sorted_symbol_order_size); - if (m_sorted_symbol_order) - memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size); - } - - return *this; - } - - inline void clear() { - if (m_lookup) { - crnd_delete_array(m_lookup); - m_lookup = 0; - m_cur_lookup_size = 0; - } - - if (m_sorted_symbol_order) { - crnd_delete_array(m_sorted_symbol_order); - m_sorted_symbol_order = NULL; - m_cur_sorted_symbol_order_size = 0; - } - } - - inline ~decoder_tables() { - if (m_lookup) - crnd_delete_array(m_lookup); - - if (m_sorted_symbol_order) - crnd_delete_array(m_sorted_symbol_order); - } - - bool init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits); - - // DO NOT use any complex classes here - it is bitwise copied. - - uint32 m_num_syms; - uint32 m_total_used_syms; - uint32 m_table_bits; - uint32 m_table_shift; - uint32 m_table_max_code; - uint32 m_decode_start_code_size; - - uint8 m_min_code_size; - uint8 m_max_code_size; - - uint32 m_max_codes[cMaxExpectedCodeSize + 1]; - int32 m_val_ptrs[cMaxExpectedCodeSize + 1]; - - uint32 m_cur_lookup_size; - uint32* m_lookup; - - uint32 m_cur_sorted_symbol_order_size; - uint16* m_sorted_symbol_order; - - inline uint32 get_unshifted_max_code(uint32 len) const { - CRND_ASSERT((len >= 1) && (len <= cMaxExpectedCodeSize)); - uint32 k = m_max_codes[len - 1]; - if (!k) - return unitycrnd::cUINT32_MAX; - return (k - 1) >> (16 - len); - } -}; - -} // namespace prefix_coding - -} // namespace unitycrnd - -// File: crnd_symbol_codec.h -namespace unitycrnd { -class static_huffman_data_model { - public: - static_huffman_data_model(); - static_huffman_data_model(const static_huffman_data_model& other); - ~static_huffman_data_model(); - - static_huffman_data_model& operator=(const static_huffman_data_model& rhs); - - bool init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit); - void clear(); - - inline bool is_valid() const { return m_pDecode_tables != NULL; } - - inline uint32 get_total_syms() const { return m_total_syms; } - - inline uint32 get_code_size(uint32 sym) const { return m_code_sizes[sym]; } - - inline const uint8* get_code_sizes() const { return m_code_sizes.empty() ? NULL : &m_code_sizes[0]; } - - public: - uint32 m_total_syms; - unitycrnd::vector m_code_sizes; - prefix_coding::decoder_tables* m_pDecode_tables; - - private: - bool prepare_decoder_tables(); - uint compute_decoder_table_bits() const; - - friend class symbol_codec; -}; - -class symbol_codec { - public: - symbol_codec(); - - bool start_decoding(const uint8* pBuf, uint32 buf_size); - bool decode_receive_static_data_model(static_huffman_data_model& model); - - uint32 decode_bits(uint32 num_bits); - uint32 decode(const static_huffman_data_model& model); - - uint64 stop_decoding(); - - public: - const uint8* m_pDecode_buf; - const uint8* m_pDecode_buf_next; - const uint8* m_pDecode_buf_end; - uint32 m_decode_buf_size; - - typedef uint32 bit_buf_type; - enum { cBitBufSize = 32U }; - bit_buf_type m_bit_buf; - - int m_bit_count; - - private: - void get_bits_init(); - uint32 get_bits(uint32 num_bits); -}; - -} // namespace unitycrnd - -namespace unitycrnd { -void crnd_assert(const char* pExp, const char* pFile, unsigned line) { - char buf[512]; - -#if defined(_WIN32) && defined(_MSC_VER) - sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp); -#else - sprintf(buf, "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp); -#endif - - crnd_output_debug_string(buf); - - puts(buf); - - if (crnd_is_debugger_present()) - crnd_debug_break(); -} - -void crnd_trace(const char* pFmt, va_list args) { - if (crnd_is_debugger_present()) { - char buf[512]; -#if defined(_WIN32) && defined(_MSC_VER) - vsprintf_s(buf, sizeof(buf), pFmt, args); -#else - vsprintf(buf, pFmt, args); -#endif - - crnd_output_debug_string(buf); - } -}; - -void crnd_trace(const char* pFmt, ...) { - va_list args; - va_start(args, pFmt); - crnd_trace(pFmt, args); - va_end(args); -}; - -} // namespace unitycrnd - -// File: checksum.cpp -// From the public domain stb.h header. -namespace unitycrnd { -uint16 crc16(const void* pBuf, uint32 len, uint16 crc) { - crc = ~crc; - - const uint8* p = reinterpret_cast(pBuf); - while (len) { - const uint16 q = *p++ ^ (crc >> 8U); - crc <<= 8U; - - uint16 r = (q >> 4U) ^ q; - crc ^= r; - r <<= 5U; - crc ^= r; - r <<= 7U; - crc ^= r; - - len--; - } - - return static_cast(~crc); -} - -} // namespace unitycrnd - -// File: crnd_vector.cpp -namespace unitycrnd { -bool elemental_vector::increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pMover) { - CRND_ASSERT(m_size <= m_capacity); - CRND_ASSERT(min_new_capacity < (0x7FFF0000U / element_size)); - - if (m_capacity >= min_new_capacity) - return true; - - uint32 new_capacity = min_new_capacity; - if ((grow_hint) && (!math::is_power_of_2(new_capacity))) - new_capacity = math::next_pow2(new_capacity); - - CRND_ASSERT(new_capacity && (new_capacity > m_capacity)); - - const uint32 desired_size = element_size * new_capacity; - size_t actual_size; - if (!pMover) { - void* new_p = crnd_realloc(m_p, desired_size, &actual_size, true); - if (!new_p) - return false; - m_p = new_p; - } else { - void* new_p = crnd_malloc(desired_size, &actual_size); - if (!new_p) - return false; - - (*pMover)(new_p, m_p, m_size); - - if (m_p) - crnd_free(m_p); - - m_p = new_p; - } - - if (actual_size > desired_size) - m_capacity = static_cast(actual_size / element_size); - else - m_capacity = new_capacity; - - return true; -} - -} // namespace unitycrnd - -// File: crnd_utils.cpp -namespace unitycrnd { -namespace utils { -uint32 compute_max_mips(uint32 width, uint32 height) { - if ((width | height) == 0) - return 0; - - uint32 num_mips = 1; - - while ((width > 1U) || (height > 1U)) { - width >>= 1U; - height >>= 1U; - num_mips++; - } - - return num_mips; -} - -} // namespace utils - -} // namespace unitycrnd - -// File: crnd_prefix_coding.cpp -namespace unitycrnd { -namespace prefix_coding { -bool decoder_tables::init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits) { - uint32 min_codes[cMaxExpectedCodeSize]; - if ((!num_syms) || (table_bits > cMaxTableBits)) - return false; - - m_num_syms = num_syms; - - uint32 num_codes[cMaxExpectedCodeSize + 1]; - utils::zero_object(num_codes); - - for (uint32 i = 0; i < num_syms; i++) { - uint32 c = pCodesizes[i]; - if (c) - num_codes[c]++; - } - - uint32 sorted_positions[cMaxExpectedCodeSize + 1]; - - uint32 cur_code = 0; - - uint32 total_used_syms = 0; - uint32 max_code_size = 0; - uint32 min_code_size = cUINT32_MAX; - for (uint32 i = 1; i <= cMaxExpectedCodeSize; i++) { - const uint32 n = num_codes[i]; - - if (!n) - m_max_codes[i - 1] = 0; //UINT_MAX; - else { - min_code_size = math::minimum(min_code_size, i); - max_code_size = math::maximum(max_code_size, i); - - min_codes[i - 1] = cur_code; - - m_max_codes[i - 1] = cur_code + n - 1; - m_max_codes[i - 1] = 1 + ((m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1)); - - m_val_ptrs[i - 1] = total_used_syms; - - sorted_positions[i] = total_used_syms; - - cur_code += n; - total_used_syms += n; - } - - cur_code <<= 1; - } - - m_total_used_syms = total_used_syms; - - if (total_used_syms > m_cur_sorted_symbol_order_size) { - m_cur_sorted_symbol_order_size = total_used_syms; - - if (!math::is_power_of_2(total_used_syms)) - m_cur_sorted_symbol_order_size = math::minimum(num_syms, math::next_pow2(total_used_syms)); - - if (m_sorted_symbol_order) - crnd_delete_array(m_sorted_symbol_order); - - m_sorted_symbol_order = crnd_new_array(m_cur_sorted_symbol_order_size); - if (!m_sorted_symbol_order) - return false; - } - - m_min_code_size = static_cast(min_code_size); - m_max_code_size = static_cast(max_code_size); - - for (uint32 i = 0; i < num_syms; i++) { - uint32 c = pCodesizes[i]; - if (c) { - CRND_ASSERT(num_codes[c]); - - uint32 sorted_pos = sorted_positions[c]++; - - CRND_ASSERT(sorted_pos < total_used_syms); - - m_sorted_symbol_order[sorted_pos] = static_cast(i); - } - } - - if (table_bits <= m_min_code_size) - table_bits = 0; - m_table_bits = table_bits; - - if (table_bits) { - uint32 table_size = 1 << table_bits; - if (table_size > m_cur_lookup_size) { - m_cur_lookup_size = table_size; - - if (m_lookup) - crnd_delete_array(m_lookup); - - m_lookup = crnd_new_array(table_size); - if (!m_lookup) - return false; - } - - memset(m_lookup, 0xFF, (uint)sizeof(m_lookup[0]) * (1UL << table_bits)); - - for (uint32 codesize = 1; codesize <= table_bits; codesize++) { - if (!num_codes[codesize]) - continue; - - const uint32 fillsize = table_bits - codesize; - const uint32 fillnum = 1 << fillsize; - - const uint32 min_code = min_codes[codesize - 1]; - const uint32 max_code = get_unshifted_max_code(codesize); - const uint32 val_ptr = m_val_ptrs[codesize - 1]; - - for (uint32 code = min_code; code <= max_code; code++) { - const uint32 sym_index = m_sorted_symbol_order[val_ptr + code - min_code]; - CRND_ASSERT(pCodesizes[sym_index] == codesize); - - for (uint32 j = 0; j < fillnum; j++) { - const uint32 t = j + (code << fillsize); - - CRND_ASSERT(t < (1U << table_bits)); - - CRND_ASSERT(m_lookup[t] == cUINT32_MAX); - - m_lookup[t] = sym_index | (codesize << 16U); - } - } - } - } - - for (uint32 i = 0; i < cMaxExpectedCodeSize; i++) - m_val_ptrs[i] -= min_codes[i]; - - m_table_max_code = 0; - m_decode_start_code_size = m_min_code_size; - - if (table_bits) { - uint32 i; - for (i = table_bits; i >= 1; i--) { - if (num_codes[i]) { - m_table_max_code = m_max_codes[i - 1]; - break; - } - } - if (i >= 1) { - m_decode_start_code_size = table_bits + 1; - for (uint32 j = table_bits + 1; j <= max_code_size; j++) { - if (num_codes[j]) { - m_decode_start_code_size = j; - break; - } - } - } - } - - // sentinels - m_max_codes[cMaxExpectedCodeSize] = cUINT32_MAX; - m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF; - - m_table_shift = 32 - m_table_bits; - return true; -} - -} // namespace prefix_codig - -} // namespace unitycrnd - -// File: crnd_platform.cpp -namespace unitycrnd { -bool crnd_is_debugger_present() { -#ifdef CRND_DEVEL - return IsDebuggerPresent() != 0; -#else - return false; -#endif -} - -void crnd_debug_break() { -#ifdef CRND_DEVEL - DebugBreak(); -#endif -} - -void crnd_output_debug_string(const char* p) { - (void)p; -#ifdef CRND_DEVEL - OutputDebugStringA(p); -#endif -} - -} // namespace unitycrnd - -// File: crnd_mem.cpp -namespace unitycrnd { -const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U; - -static void* crnd_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void*) { - void* p_new; - - if (!p) { - p_new = ::malloc(size); - - if (pActual_size) { -#ifdef _WIN32 - *pActual_size = p_new ? ::_msize(p_new) : 0; -#else - *pActual_size = p_new ? malloc_usable_size(p_new) : 0; -#endif - } - } else if (!size) { - ::free(p); - p_new = NULL; - - if (pActual_size) - *pActual_size = 0; - } else { - void* p_final_block = p; -#ifdef _WIN32 - p_new = ::_expand(p, size); -#else - p_new = NULL; -#endif - - if (p_new) - p_final_block = p_new; - else if (movable) { - p_new = ::realloc(p, size); - - if (p_new) - p_final_block = p_new; - } - - if (pActual_size) { -#ifdef _WIN32 - *pActual_size = ::_msize(p_final_block); -#else - *pActual_size = ::malloc_usable_size(p_final_block); -#endif - } - } - - return p_new; -} - -static size_t crnd_default_msize(void* p, void* pUser_data) { - pUser_data; -#ifdef _WIN32 - return p ? _msize(p) : 0; -#else - return p ? malloc_usable_size(p) : 0; -#endif -} - -static crnd_realloc_func g_pRealloc = crnd_default_realloc; -static crnd_msize_func g_pMSize = crnd_default_msize; -static void* g_pUser_data; - -void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data) { - if ((!pRealloc) || (!pMSize)) { - g_pRealloc = crnd_default_realloc; - g_pMSize = crnd_default_msize; - g_pUser_data = NULL; - } else { - g_pRealloc = pRealloc; - g_pMSize = pMSize; - g_pUser_data = pUser_data; - } -} - -static inline void crnd_mem_error(const char* p_msg) { - crnd_assert(p_msg, __FILE__, __LINE__); -} - -void* crnd_malloc(size_t size, size_t* pActual_size) { - size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U); - if (!size) - size = sizeof(uint32); - - if (size > MAX_POSSIBLE_BLOCK_SIZE) { - crnd_mem_error("crnd_malloc: size too big"); - return NULL; - } - - size_t actual_size = size; - uint8* p_new = static_cast((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data)); - - if (pActual_size) - *pActual_size = actual_size; - - if ((!p_new) || (actual_size < size)) { - crnd_mem_error("crnd_malloc: out of memory"); - return NULL; - } - - CRND_ASSERT(((uint32) reinterpret_cast(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0); - - return p_new; -} - -void* crnd_realloc(void* p, size_t size, size_t* pActual_size, bool movable) { - if ((uint32) reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) { - crnd_mem_error("crnd_realloc: bad ptr"); - return NULL; - } - - if (size > MAX_POSSIBLE_BLOCK_SIZE) { - crnd_mem_error("crnd_malloc: size too big"); - return NULL; - } - - size_t actual_size = size; - void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data); - - if (pActual_size) - *pActual_size = actual_size; - - CRND_ASSERT(((uint32) reinterpret_cast(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0); - - return p_new; -} - -void crnd_free(void* p) { - if (!p) - return; - - if ((uint32) reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) { - crnd_mem_error("crnd_free: bad ptr"); - return; - } - - (*g_pRealloc)(p, 0, NULL, true, g_pUser_data); -} - -size_t crnd_msize(void* p) { - if (!p) - return 0; - - if ((uint32) reinterpret_cast(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) { - crnd_mem_error("crnd_msize: bad ptr"); - return 0; - } - - return (*g_pMSize)(p, g_pUser_data); -} - -} // namespace unitycrnd - -// File: crnd_math.cpp -namespace unitycrnd { -namespace math { -uint32 g_bitmasks[32] = - { - 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, - 1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U, - 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, - 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, - 1U << 16U, 1U << 17U, 1U << 18U, 1U << 19U, - 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, - 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, - 1U << 28U, 1U << 29U, 1U << 30U, 1U << 31U}; - -} // namespace math -} // namespace unitycrnd - -// File: crnd_info.cpp -namespace unitycrnd { -#define CRND_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U)) - -uint32 crnd_crn_format_to_fourcc(crn_format fmt) { - switch (fmt) { - case cCRNFmtDXT1: - return CRND_FOURCC('D', 'X', 'T', '1'); - case cCRNFmtDXT3: - return CRND_FOURCC('D', 'X', 'T', '3'); - case cCRNFmtDXT5: - return CRND_FOURCC('D', 'X', 'T', '5'); - case cCRNFmtDXN_XY: - return CRND_FOURCC('A', '2', 'X', 'Y'); - case cCRNFmtDXN_YX: - return CRND_FOURCC('A', 'T', 'I', '2'); - case cCRNFmtDXT5A: - return CRND_FOURCC('A', 'T', 'I', '1'); - case cCRNFmtDXT5_CCxY: - return CRND_FOURCC('C', 'C', 'x', 'Y'); - case cCRNFmtDXT5_xGxR: - return CRND_FOURCC('x', 'G', 'x', 'R'); - case cCRNFmtDXT5_xGBR: - return CRND_FOURCC('x', 'G', 'B', 'R'); - case cCRNFmtDXT5_AGBR: - return CRND_FOURCC('A', 'G', 'B', 'R'); - case cCRNFmtETC1: - return CRND_FOURCC('E', 'T', 'C', '1'); - case cCRNFmtETC2: - return CRND_FOURCC('E', 'T', 'C', '2'); - case cCRNFmtETC2A: - return CRND_FOURCC('E', 'T', '2', 'A'); - case cCRNFmtETC1S: - return CRND_FOURCC('E', 'T', '1', 'S'); - case cCRNFmtETC2AS: - return CRND_FOURCC('E', '2', 'A', 'S'); - default: - break; - } - CRND_ASSERT(false); - return 0; -} - -crn_format crnd_get_fundamental_dxt_format(crn_format fmt) { - switch (fmt) { - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGxR: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - return cCRNFmtDXT5; - default: - break; - } - return fmt; -} - -uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt) { - switch (fmt) { - case cCRNFmtDXT1: - case cCRNFmtDXT5A: - case cCRNFmtETC1: - case cCRNFmtETC2: - case cCRNFmtETC1S: - return 4; - case cCRNFmtDXT3: - case cCRNFmtDXT5: - case cCRNFmtDXN_XY: - case cCRNFmtDXN_YX: - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGxR: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - case cCRNFmtETC2A: - case cCRNFmtETC2AS: - return 8; - default: - break; - } - CRND_ASSERT(false); - return 0; -} - -uint32 crnd_get_bytes_per_dxt_block(crn_format fmt) { - return (crnd_get_crn_format_bits_per_texel(fmt) << 4) >> 3; -} - -// TODO: tmp_header isn't used/This function is a helper to support old headers. -const crn_header* crnd_get_header(const void* pData, uint32 data_size) { - if ((!pData) || (data_size < sizeof(crn_header))) - return NULL; - - const crn_header& file_header = *static_cast(pData); - if (file_header.m_sig != crn_header::cCRNSigValue) - return NULL; - - if ((file_header.m_header_size < sizeof(crn_header)) || (data_size < file_header.m_data_size)) - return NULL; - - return &file_header; -} - -bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) { - if (pFile_info) { - if (pFile_info->m_struct_size != sizeof(crn_file_info)) - return false; - - memset(&pFile_info->m_struct_size + 1, 0, sizeof(crn_file_info) - sizeof(pFile_info->m_struct_size)); - } - - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return false; - - const uint32 header_crc = crc16(&pHeader->m_data_size, (uint32)(pHeader->m_header_size - ((const uint8*)&pHeader->m_data_size - (const uint8*)pHeader))); - if (header_crc != pHeader->m_header_crc16) - return false; - - const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size); - if (data_crc != pHeader->m_data_crc16) - return false; - - if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6)) - return false; - if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution)) - return false; - if ((pHeader->m_height < 1) || (pHeader->m_height > cCRNMaxLevelResolution)) - return false; - if ((pHeader->m_levels < 1) || (pHeader->m_levels > utils::compute_max_mips(pHeader->m_width, pHeader->m_height))) - return false; - if (((int)pHeader->m_format < cCRNFmtDXT1) || ((int)pHeader->m_format >= cCRNFmtTotal)) - return false; - - if (pFile_info) { - pFile_info->m_actual_data_size = pHeader->m_data_size; - pFile_info->m_header_size = pHeader->m_header_size; - pFile_info->m_total_palette_size = pHeader->m_color_endpoints.m_size + pHeader->m_color_selectors.m_size + pHeader->m_alpha_endpoints.m_size + pHeader->m_alpha_selectors.m_size; - pFile_info->m_tables_size = pHeader->m_tables_size; - - pFile_info->m_levels = pHeader->m_levels; - - for (uint32 i = 0; i < pHeader->m_levels; i++) { - uint32 next_ofs = pHeader->m_data_size; - - // assumes the levels are packed together sequentially - if ((i + 1) < pHeader->m_levels) - next_ofs = pHeader->m_level_ofs[i + 1]; - - pFile_info->m_level_compressed_size[i] = next_ofs - pHeader->m_level_ofs[i]; - } - - pFile_info->m_color_endpoint_palette_entries = pHeader->m_color_endpoints.m_num; - pFile_info->m_color_selector_palette_entries = pHeader->m_color_selectors.m_num; - ; - pFile_info->m_alpha_endpoint_palette_entries = pHeader->m_alpha_endpoints.m_num; - ; - pFile_info->m_alpha_selector_palette_entries = pHeader->m_alpha_selectors.m_num; - ; - } - - return true; -} - -bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo) { - if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo)) - return false; - - if (pInfo->m_struct_size != sizeof(crn_texture_info)) - return false; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return false; - - pInfo->m_width = pHeader->m_width; - pInfo->m_height = pHeader->m_height; - pInfo->m_levels = pHeader->m_levels; - pInfo->m_faces = pHeader->m_faces; - pInfo->m_format = static_cast((uint32)pHeader->m_format); - pInfo->m_bytes_per_block = pHeader->m_format == cCRNFmtDXT1 || pHeader->m_format == cCRNFmtDXT5A || pHeader->m_format == cCRNFmtETC1 || pHeader->m_format == cCRNFmtETC2 || pHeader->m_format == cCRNFmtETC1S ? 8 : 16; - pInfo->m_userdata0 = pHeader->m_userdata0; - pInfo->m_userdata1 = pHeader->m_userdata1; - - return true; -} - -bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info) { - if ((!pData) || (data_size < cCRNHeaderMinSize) || (!pLevel_info)) - return false; - - if (pLevel_info->m_struct_size != sizeof(crn_level_info)) - return false; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return false; - - if (level_index >= pHeader->m_levels) - return false; - - uint32 width = math::maximum(1U, pHeader->m_width >> level_index); - uint32 height = math::maximum(1U, pHeader->m_height >> level_index); - - pLevel_info->m_width = width; - pLevel_info->m_height = height; - pLevel_info->m_faces = pHeader->m_faces; - pLevel_info->m_blocks_x = (width + 3) >> 2; - pLevel_info->m_blocks_y = (height + 3) >> 2; - pLevel_info->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16; - pLevel_info->m_format = static_cast((uint32)pHeader->m_format); - - return true; -} - -const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize) { - if (pSize) - *pSize = 0; - - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return NULL; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return NULL; - - if (level_index >= pHeader->m_levels) - return NULL; - - uint32 cur_level_ofs = pHeader->m_level_ofs[level_index]; - - if (pSize) { - uint32 next_level_ofs = data_size; - if ((level_index + 1) < (pHeader->m_levels)) - next_level_ofs = pHeader->m_level_ofs[level_index + 1]; - - *pSize = next_level_ofs - cur_level_ofs; - } - - return static_cast(pData) + cur_level_ofs; -} - -uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size) { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return false; - - uint32 size = pHeader->m_header_size; - - size = math::maximum(size, pHeader->m_color_endpoints.m_ofs + pHeader->m_color_endpoints.m_size); - size = math::maximum(size, pHeader->m_color_selectors.m_ofs + pHeader->m_color_selectors.m_size); - size = math::maximum(size, pHeader->m_alpha_endpoints.m_ofs + pHeader->m_alpha_endpoints.m_size); - size = math::maximum(size, pHeader->m_alpha_selectors.m_ofs + pHeader->m_alpha_selectors.m_size); - size = math::maximum(size, pHeader->m_tables_ofs + pHeader->m_tables_size); - - return size; -} - -bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size) { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return false; - - const crn_header* pHeader = crnd_get_header(pData, data_size); - if (!pHeader) - return false; - - if (pHeader->m_flags & cCRNHeaderFlagSegmented) - return false; - - const uint actual_base_data_size = crnd_get_segmented_file_size(pData, data_size); - if (base_data_size < actual_base_data_size) - return false; - - memcpy(pBase_data, pData, actual_base_data_size); - - crn_header& new_header = *static_cast(pBase_data); - new_header.m_flags = new_header.m_flags | cCRNHeaderFlagSegmented; - new_header.m_data_size = actual_base_data_size; - - new_header.m_data_crc16 = crc16((const uint8*)pBase_data + new_header.m_header_size, new_header.m_data_size - new_header.m_header_size); - - new_header.m_header_crc16 = crc16(&new_header.m_data_size, new_header.m_header_size - (uint32)((const uint8*)&new_header.m_data_size - (const uint8*)&new_header)); - - CRND_ASSERT(crnd_validate_file(&new_header, actual_base_data_size, NULL)); - - return true; -} - -} // namespace unitycrnd - -// File: symbol_codec.cpp -namespace unitycrnd { -static_huffman_data_model::static_huffman_data_model() - : m_total_syms(0), - m_pDecode_tables(NULL) { -} - -static_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other) - : m_total_syms(0), - m_pDecode_tables(NULL) { - *this = other; -} - -static_huffman_data_model::~static_huffman_data_model() { - if (m_pDecode_tables) - crnd_delete(m_pDecode_tables); -} - -static_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs) { - if (this == &rhs) - return *this; - - m_total_syms = rhs.m_total_syms; - m_code_sizes = rhs.m_code_sizes; - if (m_code_sizes.get_alloc_failed()) { - clear(); - return *this; - } - - if (rhs.m_pDecode_tables) { - if (m_pDecode_tables) - *m_pDecode_tables = *rhs.m_pDecode_tables; - else - m_pDecode_tables = crnd_new(*rhs.m_pDecode_tables); - } else { - crnd_delete(m_pDecode_tables); - m_pDecode_tables = NULL; - } - - return *this; -} - -void static_huffman_data_model::clear() { - m_total_syms = 0; - m_code_sizes.clear(); - if (m_pDecode_tables) { - crnd_delete(m_pDecode_tables); - m_pDecode_tables = NULL; - } -} - -bool static_huffman_data_model::init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit) { - CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1)); - - code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize); - - if (!m_code_sizes.resize(total_syms)) - return false; - - uint32 min_code_size = cUINT32_MAX; - uint32 max_code_size = 0; - - for (uint32 i = 0; i < total_syms; i++) { - uint32 s = pCode_sizes[i]; - m_code_sizes[i] = static_cast(s); - min_code_size = math::minimum(min_code_size, s); - max_code_size = math::maximum(max_code_size, s); - } - - if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit)) - return false; - - if (max_code_size > code_size_limit) - return false; - - if (!m_pDecode_tables) - m_pDecode_tables = crnd_new(); - - if (!m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits())) - return false; - - return true; -} - -bool static_huffman_data_model::prepare_decoder_tables() { - uint32 total_syms = m_code_sizes.size(); - - CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms)); - - m_total_syms = total_syms; - - if (!m_pDecode_tables) - m_pDecode_tables = crnd_new(); - - return m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits()); -} - -uint static_huffman_data_model::compute_decoder_table_bits() const { -#if CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE - return prefix_coding::cMaxTableBits; -#else - uint32 decoder_table_bits = 0; - if (m_total_syms > 16) - decoder_table_bits = static_cast(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits)); - return decoder_table_bits; -#endif -} - -symbol_codec::symbol_codec() - : m_pDecode_buf(NULL), - m_pDecode_buf_next(NULL), - m_pDecode_buf_end(NULL), - m_decode_buf_size(0), - m_bit_buf(0), - m_bit_count(0) { -} - -// Code length encoding symbols: -// 0-16 - actual code lengths -const uint32 cMaxCodelengthCodes = 21; - -const uint32 cSmallZeroRunCode = 17; -const uint32 cLargeZeroRunCode = 18; -const uint32 cSmallRepeatCode = 19; -const uint32 cLargeRepeatCode = 20; - -const uint32 cMinSmallZeroRunSize = 3; -const uint32 cMaxSmallZeroRunSize = 10; -const uint32 cMinLargeZeroRunSize = 11; -const uint32 cMaxLargeZeroRunSize = 138; - -const uint32 cSmallMinNonZeroRunSize = 3; -const uint32 cSmallMaxNonZeroRunSize = 6; -const uint32 cLargeMinNonZeroRunSize = 7; -const uint32 cLargeMaxNonZeroRunSize = 70; - -const uint32 cSmallZeroRunExtraBits = 3; -const uint32 cLargeZeroRunExtraBits = 7; -const uint32 cSmallNonZeroRunExtraBits = 2; -const uint32 cLargeNonZeroRunExtraBits = 6; - -static const uint8 g_most_probable_codelength_codes[] = - { - cSmallZeroRunCode, cLargeZeroRunCode, - cSmallRepeatCode, cLargeRepeatCode, - - 0, 8, - 7, 9, - 6, 10, - 5, 11, - 4, 12, - 3, 13, - 2, 14, - 1, 15, - 16}; -const uint32 cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]); - -bool symbol_codec::decode_receive_static_data_model(static_huffman_data_model& model) { - const uint32 total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms)); - - if (!total_used_syms) { - model.clear(); - return true; - } - - if (!model.m_code_sizes.resize(total_used_syms)) - return false; - - memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms); - - const uint32 num_codelength_codes_to_send = decode_bits(5); - if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes)) - return false; - - static_huffman_data_model dm; - if (!dm.m_code_sizes.resize(cMaxCodelengthCodes)) - return false; - - for (uint32 i = 0; i < num_codelength_codes_to_send; i++) - dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast(decode_bits(3)); - - if (!dm.prepare_decoder_tables()) - return false; - - uint32 ofs = 0; - while (ofs < total_used_syms) { - const uint32 num_remaining = total_used_syms - ofs; - - uint32 code = decode(dm); - if (code <= 16) - model.m_code_sizes[ofs++] = static_cast(code); - else if (code == cSmallZeroRunCode) { - uint32 len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize; - if (len > num_remaining) - return false; - ofs += len; - } else if (code == cLargeZeroRunCode) { - uint32 len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize; - if (len > num_remaining) - return false; - ofs += len; - } else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode)) { - uint32 len; - if (code == cSmallRepeatCode) - len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize; - else - len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize; - - if ((!ofs) || (len > num_remaining)) - return false; - const uint32 prev = model.m_code_sizes[ofs - 1]; - if (!prev) - return false; - const uint32 end = ofs + len; - while (ofs < end) - model.m_code_sizes[ofs++] = static_cast(prev); - } else { - CRND_ASSERT(0); - return false; - } - } - - if (ofs != total_used_syms) - return false; - - return model.prepare_decoder_tables(); -} - -bool symbol_codec::start_decoding(const uint8* pBuf, uint32 buf_size) { - if (!buf_size) - return false; - - m_pDecode_buf = pBuf; - m_pDecode_buf_next = pBuf; - m_decode_buf_size = buf_size; - m_pDecode_buf_end = pBuf + buf_size; - - get_bits_init(); - - return true; -} - -void symbol_codec::get_bits_init() { - m_bit_buf = 0; - m_bit_count = 0; -} - -uint32 symbol_codec::decode_bits(uint32 num_bits) { - if (!num_bits) - return 0; - - if (num_bits > 16) { - uint32 a = get_bits(num_bits - 16); - uint32 b = get_bits(16); - - return (a << 16) | b; - } else - return get_bits(num_bits); -} - -uint32 symbol_codec::get_bits(uint32 num_bits) { - CRND_ASSERT(num_bits <= 32U); - - while (m_bit_count < (int)num_bits) { - bit_buf_type c = 0; - if (m_pDecode_buf_next != m_pDecode_buf_end) - c = *m_pDecode_buf_next++; - - m_bit_count += 8; - CRND_ASSERT(m_bit_count <= cBitBufSize); - - m_bit_buf |= (c << (cBitBufSize - m_bit_count)); - } - - uint32 result = static_cast(m_bit_buf >> (cBitBufSize - num_bits)); - - m_bit_buf <<= num_bits; - m_bit_count -= num_bits; - - return result; -} - -uint32 symbol_codec::decode(const static_huffman_data_model& model) { - const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables; - - if (m_bit_count < 24) { - if (m_bit_count < 16) { - uint32 c0 = 0, c1 = 0; - const uint8* p = m_pDecode_buf_next; - if (p < m_pDecode_buf_end) - c0 = *p++; - if (p < m_pDecode_buf_end) - c1 = *p++; - m_pDecode_buf_next = p; - m_bit_count += 16; - uint32 c = (c0 << 8) | c1; - m_bit_buf |= (c << (32 - m_bit_count)); - } else { - uint32 c = (m_pDecode_buf_next < m_pDecode_buf_end) ? *m_pDecode_buf_next++ : 0; - m_bit_count += 8; - m_bit_buf |= (c << (32 - m_bit_count)); - } - } - - uint32 k = (m_bit_buf >> 16) + 1; - uint32 sym, len; - - if (k <= pTables->m_table_max_code) { - uint32 t = pTables->m_lookup[m_bit_buf >> (32 - pTables->m_table_bits)]; - - CRND_ASSERT(t != cUINT32_MAX); - sym = t & cUINT16_MAX; - len = t >> 16; - - CRND_ASSERT(model.m_code_sizes[sym] == len); - } else { - len = pTables->m_decode_start_code_size; - - for (;;) { - if (k <= pTables->m_max_codes[len - 1]) - break; - len++; - } - - int val_ptr = pTables->m_val_ptrs[len - 1] + (m_bit_buf >> (32 - len)); - - if (((uint32)val_ptr >= model.m_total_syms)) { - // corrupted stream, or a bug - CRND_ASSERT(0); - return 0; - } - - sym = pTables->m_sorted_symbol_order[val_ptr]; - } - - m_bit_buf <<= len; - m_bit_count -= len; - - return sym; -} - -uint64 symbol_codec::stop_decoding() { - return static_cast(m_pDecode_buf_next - m_pDecode_buf); -} - -} // namespace unitycrnd - -// File: crnd_dxt.cpp -namespace unitycrnd { -const uint8 g_dxt1_to_linear[cDXT1SelectorValues] = {0U, 3U, 1U, 2U}; -const uint8 g_dxt1_from_linear[cDXT1SelectorValues] = {0U, 2U, 3U, 1U}; -const uint8 g_etc1_from_linear[cDXT1SelectorValues] = {3U, 2U, 0U, 1U}; - -const uint8 g_dxt5_to_linear[cDXT5SelectorValues] = {0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U}; -const uint8 g_dxt5_from_linear[cDXT5SelectorValues] = {0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U}; - -const uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 5, 4, 3, 2, 6, 7}; -const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 7, 6, 5, 4, 3, 2}; - -uint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint32 bias) { - uint32 r = color.r; - uint32 g = color.g; - uint32 b = color.b; - - if (scaled) { - r = (r * 31U + bias) / 255U; - g = (g * 63U + bias) / 255U; - b = (b * 31U + bias) / 255U; - } - - r = math::minimum(r, 31U); - g = math::minimum(g, 63U); - b = math::minimum(b, 31U); - - return static_cast(b | (g << 5U) | (r << 11U)); -} - -uint16 dxt1_block::pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias) { - return pack_color(color_quad_u8(r, g, b, 0), scaled, bias); -} - -color_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint32 alpha) { - uint32 b = packed_color & 31U; - uint32 g = (packed_color >> 5U) & 63U; - uint32 r = (packed_color >> 11U) & 31U; - - if (scaled) { - b = (b << 3U) | (b >> 2U); - g = (g << 2U) | (g >> 4U); - r = (r << 3U) | (r >> 2U); - } - - return color_quad_u8(r, g, b, alpha); -} - -void dxt1_block::unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled) { - color_quad_u8 c(unpack_color(packed_color, scaled, 0)); - r = c.r; - g = c.g; - b = c.b; -} - -uint32 dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1) { - color_quad_u8 c0(unpack_color(color0, true)); - color_quad_u8 c1(unpack_color(color1, true)); - - pDst[0] = c0; - pDst[1] = c1; - pDst[2].set((c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U); - pDst[3].set(0, 0, 0, 0); - - return 3; -} - -uint32 dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1) { - color_quad_u8 c0(unpack_color(color0, true)); - color_quad_u8 c1(unpack_color(color1, true)); - - pDst[0] = c0; - pDst[1] = c1; - - // 12/14/09 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ? - // Turns out some GPU's round and some don't. Great. - //pDst[2].set( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U); - //pDst[3].set( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U); - - pDst[2].set((c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U); - pDst[3].set((c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U); - - return 4; -} - -uint32 dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1) { - if (color0 > color1) - return get_block_colors4(pDst, color0, color1); - else - return get_block_colors3(pDst, color0, color1); -} - -color_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha) { - CRND_ASSERT(index < 2); - return unpack_color(static_cast((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha); -} - -uint32 dxt1_block::pack_endpoints(uint32 lo, uint32 hi) { - CRND_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU)); - return lo | (hi << 16U); -} - -void dxt3_block::set_alpha(uint32 x, uint32 y, uint32 value, bool scaled) { - CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize)); - - if (scaled) { - CRND_ASSERT(value <= 0xFF); - value = (value * 15U + 128U) / 255U; - } else { - CRND_ASSERT(value <= 0xF); - } - - uint32 ofs = (y << 1U) + (x >> 1U); - uint32 c = m_alpha[ofs]; - - c &= ~(0xF << ((x & 1U) << 2U)); - c |= (value << ((x & 1U) << 2U)); - - m_alpha[ofs] = static_cast(c); -} - -uint32 dxt3_block::get_alpha(uint32 x, uint32 y, bool scaled) const { - CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize)); - - uint32 value = m_alpha[(y << 1U) + (x >> 1U)]; - if (x & 1) - value >>= 4; - value &= 0xF; - - if (scaled) - value = (value << 4U) | value; - - return value; -} - -uint32 dxt5_block::get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h) { - pDst[0].a = static_cast(l); - pDst[1].a = static_cast(h); - pDst[2].a = static_cast((l * 4 + h) / 5); - pDst[3].a = static_cast((l * 3 + h * 2) / 5); - pDst[4].a = static_cast((l * 2 + h * 3) / 5); - pDst[5].a = static_cast((l + h * 4) / 5); - pDst[6].a = 0; - pDst[7].a = 255; - return 6; -} - -uint32 dxt5_block::get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h) { - pDst[0].a = static_cast(l); - pDst[1].a = static_cast(h); - pDst[2].a = static_cast((l * 6 + h) / 7); - pDst[3].a = static_cast((l * 5 + h * 2) / 7); - pDst[4].a = static_cast((l * 4 + h * 3) / 7); - pDst[5].a = static_cast((l * 3 + h * 4) / 7); - pDst[6].a = static_cast((l * 2 + h * 5) / 7); - pDst[7].a = static_cast((l + h * 6) / 7); - return 8; -} - -uint32 dxt5_block::get_block_values(color_quad_u8* pDst, uint32 l, uint32 h) { - if (l > h) - return get_block_values8(pDst, l, h); - else - return get_block_values6(pDst, l, h); -} - -uint32 dxt5_block::get_block_values6(uint32* pDst, uint32 l, uint32 h) { - pDst[0] = l; - pDst[1] = h; - pDst[2] = (l * 4 + h) / 5; - pDst[3] = (l * 3 + h * 2) / 5; - pDst[4] = (l * 2 + h * 3) / 5; - pDst[5] = (l + h * 4) / 5; - pDst[6] = 0; - pDst[7] = 255; - return 6; -} - -uint32 dxt5_block::get_block_values8(uint32* pDst, uint32 l, uint32 h) { - pDst[0] = l; - pDst[1] = h; - pDst[2] = (l * 6 + h) / 7; - pDst[3] = (l * 5 + h * 2) / 7; - pDst[4] = (l * 4 + h * 3) / 7; - pDst[5] = (l * 3 + h * 4) / 7; - pDst[6] = (l * 2 + h * 5) / 7; - pDst[7] = (l + h * 6) / 7; - return 8; -} - -uint32 dxt5_block::unpack_endpoint(uint32 packed, uint32 index) { - CRND_ASSERT(index < 2); - return (packed >> (8 * index)) & 0xFF; -} - -uint32 dxt5_block::pack_endpoints(uint32 lo, uint32 hi) { - CRND_ASSERT((lo <= 0xFF) && (hi <= 0xFF)); - return lo | (hi << 8U); -} - -uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) { - if (l > h) - return get_block_values8(pDst, l, h); - else - return get_block_values6(pDst, l, h); -} - -} // namespace unitycrnd - -// File: crnd_decode.cpp - -namespace unitycrnd { - -class crn_unpacker { - public: - inline crn_unpacker() - : m_magic(cMagicValue), - m_pData(NULL), - m_data_size(0), - m_pHeader(NULL) { - } - - inline ~crn_unpacker() { - m_magic = 0; - } - - inline bool is_valid() const { return m_magic == cMagicValue; } - - bool init(const void* pData, uint32 data_size) { - m_pHeader = crnd_get_header(pData, data_size); - if (!m_pHeader) - return false; - - m_pData = static_cast(pData); - m_data_size = data_size; - - if (!init_tables()) - return false; - - if (!decode_palettes()) - return false; - - return true; - } - - bool unpack_level( - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) { - uint32 cur_level_ofs = m_pHeader->m_level_ofs[level_index]; - - uint32 next_level_ofs = m_data_size; - if ((level_index + 1) < (m_pHeader->m_levels)) - next_level_ofs = m_pHeader->m_level_ofs[level_index + 1]; - - CRND_ASSERT(next_level_ofs > cur_level_ofs); - - return unpack_level(m_pData + cur_level_ofs, next_level_ofs - cur_level_ofs, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); - } - - bool unpack_level( - const void* pSrc, uint32 src_size_in_bytes, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) { - -#ifdef CRND_BUILD_DEBUG - for (uint32 f = 0; f < m_pHeader->m_faces; f++) - if (!pDst[f]) - return false; -#endif - - const uint32 width = math::maximum(m_pHeader->m_width >> level_index, 1U); - const uint32 height = math::maximum(m_pHeader->m_height >> level_index, 1U); - const uint32 blocks_x = (width + 3U) >> 2U; - const uint32 blocks_y = (height + 3U) >> 2U; - const uint32 block_size = m_pHeader->m_format == cCRNFmtDXT1 || m_pHeader->m_format == cCRNFmtDXT5A || m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC1S ? 8 : 16; - - uint32 minimal_row_pitch = block_size * blocks_x; - if (!row_pitch_in_bytes) - row_pitch_in_bytes = minimal_row_pitch; - else if ((row_pitch_in_bytes < minimal_row_pitch) || (row_pitch_in_bytes & 3)) - return false; - if (dst_size_in_bytes < row_pitch_in_bytes * blocks_y) - return false; - - if (!m_codec.start_decoding(static_cast(pSrc), src_size_in_bytes)) - return false; - - bool status = false; - switch (m_pHeader->m_format) { - case cCRNFmtDXT1: - case cCRNFmtETC1S: - status = unpack_dxt1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtDXT5: - case cCRNFmtDXT5_CCxY: - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - case cCRNFmtDXT5_xGxR: - case cCRNFmtETC2AS: - status = unpack_dxt5((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtDXT5A: - status = unpack_dxt5a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtDXN_XY: - case cCRNFmtDXN_YX: - status = unpack_dxn((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtETC1: - status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtETC2: - status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - case cCRNFmtETC2A: - status = unpack_etc2a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y); - break; - default: - return false; - } - if (!status) - return false; - - m_codec.stop_decoding(); - return true; - } - - inline const void* get_data() const { return m_pData; } - inline uint32 get_data_size() const { return m_data_size; } - - private: - enum { cMagicValue = 0x1EF9CABD }; - uint32 m_magic; - - const uint8* m_pData; - uint32 m_data_size; - const crn_header* m_pHeader; - - symbol_codec m_codec; - - static_huffman_data_model m_reference_encoding_dm; - static_huffman_data_model m_endpoint_delta_dm[2]; - static_huffman_data_model m_selector_delta_dm[2]; - - unitycrnd::vector m_color_endpoints; - unitycrnd::vector m_color_selectors; - - unitycrnd::vector m_alpha_endpoints; - unitycrnd::vector m_alpha_selectors; - - struct block_buffer_element { - uint16 endpoint_reference; - uint16 color_endpoint_index; - uint16 alpha0_endpoint_index; - uint16 alpha1_endpoint_index; - }; - unitycrnd::vector m_block_buffer; - - bool init_tables() { - if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size)) - return false; - - if (!m_codec.decode_receive_static_data_model(m_reference_encoding_dm)) - return false; - - if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num)) - return false; - - if (m_pHeader->m_color_endpoints.m_num) { - if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[0])) - return false; - if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[0])) - return false; - } - - if (m_pHeader->m_alpha_endpoints.m_num) { - if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[1])) - return false; - if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[1])) - return false; - } - - m_codec.stop_decoding(); - - return true; - } - - bool decode_palettes() { - if (m_pHeader->m_color_endpoints.m_num) { - if (!decode_color_endpoints()) - return false; - if (!decode_color_selectors()) - return false; - } - - if (m_pHeader->m_alpha_endpoints.m_num) { - if (!decode_alpha_endpoints()) - return false; - if (!(m_pHeader->m_format == cCRNFmtETC2AS ? decode_alpha_selectors_etcs() : m_pHeader->m_format == cCRNFmtETC2A ? decode_alpha_selectors_etc() : decode_alpha_selectors())) - return false; - } - - return true; - } - - bool decode_color_endpoints() { - const uint32 num_color_endpoints = m_pHeader->m_color_endpoints.m_num; - const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A || m_pHeader->m_format == cCRNFmtETC1S || m_pHeader->m_format == cCRNFmtETC2AS; - const bool has_subblocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A; - - if (!m_color_endpoints.resize(num_color_endpoints)) - return false; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_endpoints.m_ofs, m_pHeader->m_color_endpoints.m_size)) - return false; - - static_huffman_data_model dm[2]; - for (uint32 i = 0; i < (has_etc_color_blocks ? 1 : 2); i++) - if (!m_codec.decode_receive_static_data_model(dm[i])) - return false; - - uint32 a = 0, b = 0, c = 0; - uint32 d = 0, e = 0, f = 0; - - uint32* CRND_RESTRICT pDst = &m_color_endpoints[0]; - - for (uint32 i = 0; i < num_color_endpoints; i++) { - if (has_etc_color_blocks) { - for (b = 0; b < 32; b += 8) - a += m_codec.decode(dm[0]) << b; - a &= 0x1F1F1F1F; - *pDst++ = has_subblocks ? a : (a & 0x07000000) << 5 | (a & 0x07000000) << 2 | 0x02000000 | (a & 0x001F1F1F) << 3; - } else { - a = (a + m_codec.decode(dm[0])) & 31; - b = (b + m_codec.decode(dm[1])) & 63; - c = (c + m_codec.decode(dm[0])) & 31; - d = (d + m_codec.decode(dm[0])) & 31; - e = (e + m_codec.decode(dm[1])) & 63; - f = (f + m_codec.decode(dm[0])) & 31; - *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U); - } - } - - m_codec.stop_decoding(); - - return true; - } - - bool decode_color_selectors() { - const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A || m_pHeader->m_format == cCRNFmtETC1S || m_pHeader->m_format == cCRNFmtETC2AS; - const bool has_subblocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A; - m_codec.start_decoding(m_pData + m_pHeader->m_color_selectors.m_ofs, m_pHeader->m_color_selectors.m_size); - static_huffman_data_model dm; - m_codec.decode_receive_static_data_model(dm); - m_color_selectors.resize(m_pHeader->m_color_selectors.m_num << (has_subblocks ? 1 : 0)); - for (uint32 s = 0, i = 0; i < m_pHeader->m_color_selectors.m_num; i++) { - for (uint32 j = 0; j < 32; j += 4) - s ^= m_codec.decode(dm) << j; - if (has_etc_color_blocks) { - for (uint32 selector = (~s & 0xAAAAAAAA) | (~(s ^ s >> 1) & 0x55555555), t = 8, h = 0; h < 4; h++, t -= 15) { - for (uint32 w = 0; w < 4; w++, t += 4) { - if (has_subblocks) { - uint32 s0 = selector >> (w << 3 | h << 1); - m_color_selectors[i << 1] |= ((s0 >> 1 & 1) | (s0 & 1) << 16) << (t & 15); - } - uint32 s1 = selector >> (h << 3 | w << 1); - m_color_selectors[has_subblocks ? i << 1 | 1 : i] |= ((s1 >> 1 & 1) | (s1 & 1) << 16) << (t & 15); - } - } - } else { - m_color_selectors[i] = ((s ^ s << 1) & 0xAAAAAAAA) | (s >> 1 & 0x55555555); - } - } - m_codec.stop_decoding(); - return true; - } - - bool decode_alpha_endpoints() { - const uint32 num_alpha_endpoints = m_pHeader->m_alpha_endpoints.m_num; - - if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_endpoints.m_ofs, m_pHeader->m_alpha_endpoints.m_size)) - return false; - - static_huffman_data_model dm; - if (!m_codec.decode_receive_static_data_model(dm)) - return false; - - if (!m_alpha_endpoints.resize(num_alpha_endpoints)) - return false; - - uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0]; - uint32 a = 0, b = 0; - - for (uint32 i = 0; i < num_alpha_endpoints; i++) { - a = (a + m_codec.decode(dm)) & 255; - b = (b + m_codec.decode(dm)) & 255; - *pDst++ = (uint16)(a | (b << 8)); - } - - m_codec.stop_decoding(); - - return true; - } - - bool decode_alpha_selectors() { - m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size); - static_huffman_data_model dm; - m_codec.decode_receive_static_data_model(dm); - m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 3); - uint8 dxt5_from_linear[64]; - for (uint32 i = 0; i < 64; i++) - dxt5_from_linear[i] = g_dxt5_from_linear[i & 7] | g_dxt5_from_linear[i >> 3] << 3; - for (uint32 s0_linear = 0, s1_linear = 0, i = 0; i < m_alpha_selectors.size();) { - uint32 s0 = 0, s1 = 0; - for (uint32 j = 0; j < 24; s0 |= dxt5_from_linear[s0_linear >> j & 0x3F] << j, j += 6) - s0_linear ^= m_codec.decode(dm) << j; - for (uint32 j = 0; j < 24; s1 |= dxt5_from_linear[s1_linear >> j & 0x3F] << j, j += 6) - s1_linear ^= m_codec.decode(dm) << j; - m_alpha_selectors[i++] = s0; - m_alpha_selectors[i++] = s0 >> 16 | s1 << 8; - m_alpha_selectors[i++] = s1 >> 8; - } - m_codec.stop_decoding(); - return true; - } - - bool decode_alpha_selectors_etc() { - m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size); - static_huffman_data_model dm; - m_codec.decode_receive_static_data_model(dm); - m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 6); - uint8 s_linear[8] = {}; - uint8* data = (uint8*)m_alpha_selectors.begin(); - for (uint i = 0; i < m_alpha_selectors.size(); i += 6, data += 12) { - for (uint s_group = 0, p = 0; p < 16; p++) { - s_group = p & 1 ? s_group >> 3 : s_linear[p >> 1] ^= m_codec.decode(dm); - uint8 s = s_group & 7; - if (s <= 3) - s = 3 - s; - uint8 d = 3 * (p + 1); - uint8 byte_offset = d >> 3; - uint8 bit_offset = d & 7; - data[byte_offset] |= s << (8 - bit_offset); - if (bit_offset < 3) - data[byte_offset - 1] |= s >> bit_offset; - d += 9 * ((p & 3) - (p >> 2)); - byte_offset = d >> 3; - bit_offset = d & 7; - data[byte_offset + 6] |= s << (8 - bit_offset); - if (bit_offset < 3) - data[byte_offset + 5] |= s >> bit_offset; - } - } - m_codec.stop_decoding(); - return true; - } - - bool decode_alpha_selectors_etcs() { - m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size); - static_huffman_data_model dm; - m_codec.decode_receive_static_data_model(dm); - m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 3); - uint8 s_linear[8] = {}; - uint8* data = (uint8*)m_alpha_selectors.begin(); - for (uint i = 0; i < (m_alpha_selectors.size() << 1); i += 6) { - for (uint s_group = 0, p = 0; p < 16; p++) { - s_group = p & 1 ? s_group >> 3 : s_linear[p >> 1] ^= m_codec.decode(dm); - uint8 s = s_group & 7; - if (s <= 3) - s = 3 - s; - uint8 d = 3 * (p + 1) + 9 * ((p & 3) - (p >> 2)); - uint8 byte_offset = d >> 3; - uint8 bit_offset = d & 7; - data[i + byte_offset] |= s << (8 - bit_offset); - if (bit_offset < 3) - data[i + byte_offset - 1] |= s >> bit_offset; - } - } - m_codec.stop_decoding(); - return true; - } - - static inline uint32 tiled_offset_2d_outer(uint32 y, uint32 AlignedWidth, uint32 LogBpp) { - uint32 Macro = ((y >> 5) * (AlignedWidth >> 5)) << (LogBpp + 7); - uint32 Micro = ((y & 6) << 2) << LogBpp; - - return Macro + - ((Micro & ~15) << 1) + - (Micro & 15) + - ((y & 8) << (3 + LogBpp)) + ((y & 1) << 4); - } - - static inline uint32 tiled_offset_2d_inner(uint32 x, uint32 y, uint32 LogBpp, uint32 BaseOffset) { - uint32 Macro = (x >> 5) << (LogBpp + 7); - uint32 Micro = (x & 7) << LogBpp; - uint32 Offset = BaseOffset + Macro + ((Micro & ~15) << 1) + (Micro & 15); - - return ((Offset & ~511) << 3) + ((Offset & 448) << 2) + (Offset & 63) + - ((y & 16) << 7) + - (((((y & 8) >> 2) + (x >> 3)) & 3) << 6); - } - - static inline void limit(uint& x, uint n) { - int v = x - n; - int msk = (v >> 31); - x = (x & msk) | (v & ~msk); - } - - bool unpack_dxt1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1); - - if (m_block_buffer.size() < width) - m_block_buffer.resize(width); - - uint32 color_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 2) { - visible = visible && x < output_width; - if (!(y & 1) && !(x & 1)) - reference_group = m_codec.decode(m_reference_encoding_dm); - block_buffer_element &buffer = m_block_buffer[x]; - uint8 endpoint_reference; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - endpoint_reference = reference_group & 3; - reference_group >>= 2; - buffer.endpoint_reference = reference_group & 3; - reference_group >>= 2; - } - if (!endpoint_reference) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - buffer.color_endpoint_index = color_endpoint_index; - } else if (endpoint_reference == 1) { - buffer.color_endpoint_index = color_endpoint_index; - } else { - color_endpoint_index = buffer.color_endpoint_index; - } - uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]); - if (visible) { - pData[0] = m_color_endpoints[color_endpoint_index]; - pData[1] = m_color_selectors[color_selector_index]; - } - } - } - } - return true; - } - - bool unpack_dxt5(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2); - - if (m_block_buffer.size() < width) - m_block_buffer.resize(width); - - uint32 color_endpoint_index = 0; - uint32 alpha0_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 4) { - visible = visible && x < output_width; - if (!(y & 1) && !(x & 1)) - reference_group = m_codec.decode(m_reference_encoding_dm); - block_buffer_element &buffer = m_block_buffer[x]; - uint8 endpoint_reference; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - endpoint_reference = reference_group & 3; - reference_group >>= 2; - buffer.endpoint_reference = reference_group & 3; - reference_group >>= 2; - } - if (!endpoint_reference) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - buffer.color_endpoint_index = color_endpoint_index; - alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); - if (alpha0_endpoint_index >= num_alpha_endpoints) - alpha0_endpoint_index -= num_alpha_endpoints; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else if (endpoint_reference == 1) { - buffer.color_endpoint_index = color_endpoint_index; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else { - color_endpoint_index = buffer.color_endpoint_index; - alpha0_endpoint_index = buffer.alpha0_endpoint_index; - } - uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]); - uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]); - if (visible) { - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; - pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); - pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - pData[2] = m_color_endpoints[color_endpoint_index]; - pData[3] = m_color_selectors[color_selector_index]; - } - } - } - } - return true; - } - - bool unpack_dxn(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2); - - if (m_block_buffer.size() < width) - m_block_buffer.resize(width); - - uint32 alpha0_endpoint_index = 0; - uint32 alpha1_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 4) { - visible = visible && x < output_width; - if (!(y & 1) && !(x & 1)) - reference_group = m_codec.decode(m_reference_encoding_dm); - block_buffer_element &buffer = m_block_buffer[x]; - uint8 endpoint_reference; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - endpoint_reference = reference_group & 3; - reference_group >>= 2; - buffer.endpoint_reference = reference_group & 3; - reference_group >>= 2; - } - if (!endpoint_reference) { - alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); - if (alpha0_endpoint_index >= num_alpha_endpoints) - alpha0_endpoint_index -= num_alpha_endpoints; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - alpha1_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); - if (alpha1_endpoint_index >= num_alpha_endpoints) - alpha1_endpoint_index -= num_alpha_endpoints; - buffer.alpha1_endpoint_index = alpha1_endpoint_index; - } else if (endpoint_reference == 1) { - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - buffer.alpha1_endpoint_index = alpha1_endpoint_index; - } else { - alpha0_endpoint_index = buffer.alpha0_endpoint_index; - alpha1_endpoint_index = buffer.alpha1_endpoint_index; - } - uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]); - uint32 alpha1_selector_index = m_codec.decode(m_selector_delta_dm[1]); - if (visible) { - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; - const uint16* pAlpha1_selectors = &m_alpha_selectors[alpha1_selector_index * 3]; - pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); - pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - pData[2] = m_alpha_endpoints[alpha1_endpoint_index] | (pAlpha1_selectors[0] << 16); - pData[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16); - } - } - } - } - return true; - } - - bool unpack_dxt5a(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 1); - - if (m_block_buffer.size() < width) - m_block_buffer.resize(width); - - uint32 alpha0_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 2) { - visible = visible && x < output_width; - if (!(y & 1) && !(x & 1)) - reference_group = m_codec.decode(m_reference_encoding_dm); - block_buffer_element &buffer = m_block_buffer[x]; - uint8 endpoint_reference; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - endpoint_reference = reference_group & 3; - reference_group >>= 2; - buffer.endpoint_reference = reference_group & 3; - reference_group >>= 2; - } - if (!endpoint_reference) { - alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); - if (alpha0_endpoint_index >= num_alpha_endpoints) - alpha0_endpoint_index -= num_alpha_endpoints; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else if (endpoint_reference == 1) { - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else { - alpha0_endpoint_index = buffer.alpha0_endpoint_index; - } - uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]); - if (visible) { - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; - pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); - pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - } - } - } - } - return true; - } - - bool unpack_etc1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1); - - if (m_block_buffer.size() < width << 1) - m_block_buffer.resize(width << 1); - - uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 2) { - visible = visible && x < output_width; - block_buffer_element &buffer = m_block_buffer[x << 1]; - uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4]; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - reference_group = m_codec.decode(m_reference_encoding_dm); - endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12); - buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12); - } - if (!(endpoint_reference & 3)) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - buffer.color_endpoint_index = color_endpoint_index; - } else if ((endpoint_reference & 3) == 1) { - buffer.color_endpoint_index = color_endpoint_index; - } else if ((endpoint_reference & 3) == 3) { - buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index; - } else { - color_endpoint_index = buffer.color_endpoint_index; - } - endpoint_reference >>= 2; - *(uint32*)&e0 = m_color_endpoints[color_endpoint_index]; - uint32 selector_index = m_codec.decode(m_selector_delta_dm[0]); - if (endpoint_reference) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - } - diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index; - m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index; - *(uint32*)&e1 = m_color_endpoints[color_endpoint_index]; - if (visible) { - uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1; - for (uint c = 0; diff && c < 3; c++) - diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0; - for (uint c = 0; c < 3; c++) - block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1; - block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip; - pData[0] = *(uint32*)&block_endpoint; - pData[1] = m_color_selectors[selector_index << 1 | flip]; - } - } - } - } - return true; - } - - bool unpack_etc2a(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) { - const uint32 num_color_endpoints = m_color_endpoints.size(); - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); - const uint32 width = output_width + 1 & ~1; - const uint32 height = output_height + 1 & ~1; - const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 2); - - if (m_block_buffer.size() < width << 1) - m_block_buffer.resize(width << 1); - - uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0, alpha0_endpoint_index = 0, diagonal_alpha0_endpoint_index = 0; - uint8 reference_group = 0; - - for (uint32 f = 0; f < m_pHeader->m_faces; f++) { - uint32* pData = (uint32*)pDst[f]; - for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) { - bool visible = y < output_height; - for (uint32 x = 0; x < width; x++, pData += 4) { - visible = visible && x < output_width; - block_buffer_element &buffer = m_block_buffer[x << 1]; - uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4]; - if (y & 1) { - endpoint_reference = buffer.endpoint_reference; - } else { - reference_group = m_codec.decode(m_reference_encoding_dm); - endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12); - buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12); - } - if (!(endpoint_reference & 3)) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); - if (alpha0_endpoint_index >= num_alpha_endpoints) - alpha0_endpoint_index -= num_alpha_endpoints; - buffer.color_endpoint_index = color_endpoint_index; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else if ((endpoint_reference & 3) == 1) { - buffer.color_endpoint_index = color_endpoint_index; - buffer.alpha0_endpoint_index = alpha0_endpoint_index; - } else if ((endpoint_reference & 3) == 3) { - buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index; - buffer.alpha0_endpoint_index = alpha0_endpoint_index = diagonal_alpha0_endpoint_index; - } else { - color_endpoint_index = buffer.color_endpoint_index; - alpha0_endpoint_index = buffer.alpha0_endpoint_index; - } - endpoint_reference >>= 2; - *(uint32*)&e0 = m_color_endpoints[color_endpoint_index]; - uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]); - uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]); - if (endpoint_reference) { - color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); - if (color_endpoint_index >= num_color_endpoints) - color_endpoint_index -= num_color_endpoints; - } - *(uint32*)&e1 = m_color_endpoints[color_endpoint_index]; - diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index; - diagonal_alpha0_endpoint_index = m_block_buffer[x << 1 | 1].alpha0_endpoint_index; - m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index; - m_block_buffer[x << 1 | 1].alpha0_endpoint_index = alpha0_endpoint_index; - if (visible) { - uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1; - for (uint c = 0; diff && c < 3; c++) - diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0; - for (uint c = 0; c < 3; c++) - block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1; - block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip; - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 6 + (flip ? 3 : 0)]; - pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | pAlpha0_selectors[0] << 16; - pData[1] = pAlpha0_selectors[1] | pAlpha0_selectors[2] << 16; - pData[2] = *(uint32*)&block_endpoint; - pData[3] = m_color_selectors[color_selector_index << 1 | flip]; - } - } - } - } - return true; - } - -}; - -crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size) { - if ((!pData) || (data_size < cCRNHeaderMinSize)) - return NULL; - - crn_unpacker* p = crnd_new(); - if (!p) - return NULL; - - if (!p->init(pData, data_size)) { - crnd_delete(p); - return NULL; - } - - return p; -} - -bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size) { - if (!pContext) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - if (ppData) - *ppData = pUnpacker->get_data(); - - if (pData_size) - *pData_size = pUnpacker->get_data_size(); - - return true; -} - -bool crnd_unpack_level( - crnd_unpack_context pContext, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) { - if ((!pContext) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels)) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - return pUnpacker->unpack_level(pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); -} - -bool crnd_unpack_level_segmented( - crnd_unpack_context pContext, - const void* pSrc, uint32 src_size_in_bytes, - void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index) { - if ((!pContext) || (!pSrc) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels)) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - return pUnpacker->unpack_level(pSrc, src_size_in_bytes, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index); -} - -bool crnd_unpack_end(crnd_unpack_context pContext) { - if (!pContext) - return false; - - crn_unpacker* pUnpacker = static_cast(pContext); - - if (!pUnpacker->is_valid()) - return false; - - crnd_delete(pUnpacker); - - return true; -} - -} // namespace unitycrnd - -#endif // CRND_INCLUDE_CRND_H - -//------------------------------------------------------------------------------ -// -// crn_decomp.h uses the ZLIB license: -// http://opensource.org/licenses/Zlib -// -// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//------------------------------------------------------------------------------ diff --git a/Texture2DDecoderNative/unitycrunch/crn_defs.h b/Texture2DDecoderNative/unitycrunch/crn_defs.h deleted file mode 100644 index 8d018e1..0000000 --- a/Texture2DDecoderNative/unitycrunch/crn_defs.h +++ /dev/null @@ -1,291 +0,0 @@ -#ifndef CRND_INCLUDE_CRN_DEFS_H -#define CRND_INCLUDE_CRN_DEFS_H - -// Include crnlib.h (only to bring in some basic CRN-related types). -#include "crnlib.h" - -#define CRND_LIB_VERSION 104 -#define CRND_VERSION_STRING "01.04" - -#ifdef _DEBUG -#define CRND_BUILD_DEBUG -#else -#define CRND_BUILD_RELEASE -#endif - -// CRN decompression API -namespace unitycrnd { -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef uint32 uint32; -typedef unsigned int uint; -typedef signed int int32; -#ifdef __GNUC__ -typedef unsigned long long uint64; -typedef long long int64; -#else -typedef unsigned __int64 uint64; -typedef signed __int64 int64; -#endif - -// The crnd library assumes all allocation blocks have at least CRND_MIN_ALLOC_ALIGNMENT alignment. -const uint32 CRND_MIN_ALLOC_ALIGNMENT = sizeof(uint32) * 2U; - -// realloc callback: -// Used to allocate, resize, or free memory blocks. -// If p is NULL, the realloc function attempts to allocate a block of at least size bytes. Returns NULL on out of memory. -// *pActual_size must be set to the actual size of the allocated block, which must be greater than or equal to the requested size. -// If p is not NULL, and size is 0, the realloc function frees the specified block, and always returns NULL. *pActual_size should be set to 0. -// If p is not NULL, and size is non-zero, the realloc function attempts to resize the specified block: -// If movable is false, the realloc function attempts to shrink or expand the block in-place. NULL is returned if the block cannot be resized in place, or if the -// underlying heap implementation doesn't support in-place resizing. Otherwise, the pointer to the original block is returned. -// If movable is true, it is permissible to move the block's contents if it cannot be resized in place. NULL is returned if the block cannot be resized in place, and there -// is not enough memory to relocate the block. -// In all cases, *pActual_size must be set to the actual size of the allocated block, whether it was successfully resized or not. -typedef void* (*crnd_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data); - -// msize callback: Returns the size of the memory block in bytes, or 0 if the pointer or block is invalid. -typedef size_t (*crnd_msize_func)(void* p, void* pUser_data); - -// crnd_set_memory_callbacks() - Use to override the crnd library's memory allocation functions. -// If any input parameters are NULL, the memory callback functions are reset to the default functions. -// The default functions call malloc(), free(), _msize(), _expand(), etc. -void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data); - -struct crn_file_info { - inline crn_file_info() - : m_struct_size(sizeof(crn_file_info)) {} - - uint32 m_struct_size; - uint32 m_actual_data_size; - uint32 m_header_size; - uint32 m_total_palette_size; - uint32 m_tables_size; - uint32 m_levels; - uint32 m_level_compressed_size[cCRNMaxLevels]; - uint32 m_color_endpoint_palette_entries; - uint32 m_color_selector_palette_entries; - uint32 m_alpha_endpoint_palette_entries; - uint32 m_alpha_selector_palette_entries; -}; - -struct crn_texture_info { - inline crn_texture_info() - : m_struct_size(sizeof(crn_texture_info)) {} - - uint32 m_struct_size; - uint32 m_width; - uint32 m_height; - uint32 m_levels; - uint32 m_faces; - uint32 m_bytes_per_block; - uint32 m_userdata0; - uint32 m_userdata1; - crn_format m_format; -}; - -struct crn_level_info { - inline crn_level_info() - : m_struct_size(sizeof(crn_level_info)) {} - - uint32 m_struct_size; - uint32 m_width; - uint32 m_height; - uint32 m_faces; - uint32 m_blocks_x; - uint32 m_blocks_y; - uint32 m_bytes_per_block; - crn_format m_format; -}; - -// Returns the FOURCC format code corresponding to the specified CRN format. -uint32 crnd_crn_format_to_fourcc(crn_format fmt); - -// Returns the fundamental GPU format given a potentially swizzled DXT5 crn_format. -crn_format crnd_get_fundamental_dxt_format(crn_format fmt); - -// Returns the size of the crn_format in bits/texel (either 4 or 8). -uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt); - -// Returns the number of bytes per DXTn block (8 or 16). -uint32 crnd_get_bytes_per_dxt_block(crn_format fmt); - -// Validates the entire file by checking the header and data CRC's. -// This is not something you want to be doing much! -// The crn_file_info.m_struct_size field must be set before calling this function. -bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info); - -// Retrieves texture information from the CRN file. -// The crn_texture_info.m_struct_size field must be set before calling this function. -bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pTexture_info); - -// Retrieves mipmap level specific information from the CRN file. -// The crn_level_info.m_struct_size field must be set before calling this function. -bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info); - -// Transcode/unpack context handle. -typedef void* crnd_unpack_context; - -// crnd_unpack_begin() - Decompresses the texture's decoder tables and endpoint/selector palettes. -// Once you call this function, you may call crnd_unpack_level() to unpack one or more mip levels. -// Don't call this once per mip level (unless you absolutely must)! -// This function allocates enough memory to hold: Huffman decompression tables, and the endpoint/selector palettes (color and/or alpha). -// Worst case allocation is approx. 200k, assuming all palettes contain 8192 entries. -// pData must point to a buffer holding all of the compressed .CRN file data. -// This buffer must be stable until crnd_unpack_end() is called. -// Returns NULL if out of memory, or if any of the input parameters are invalid. -crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size); - -// Returns a pointer to the compressed .CRN data associated with a crnd_unpack_context. -// Returns false if any of the input parameters are invalid. -bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size); - -// crnd_unpack_level() - Transcodes the specified mipmap level to a destination buffer in cached or write combined memory. -// pContext - Context created by a call to crnd_unpack_begin(). -// ppDst - A pointer to an array of 1 or 6 destination buffer pointers. Cubemaps require an array of 6 pointers, 2D textures require an array of 1 pointer. -// dst_size_in_bytes - Optional size of each destination buffer. Only used for debugging - OK to set to UINT32_MAX. -// row_pitch_in_bytes - The pitch in bytes from one row of DXT blocks to the next. Must be a multiple of 4. -// level_index - mipmap level index, where 0 is the largest/first level. -// Returns false if any of the input parameters, or the compressed stream, are invalid. -// This function does not allocate any memory. -bool crnd_unpack_level( - crnd_unpack_context pContext, - void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index); - -// crnd_unpack_level_segmented() - Unpacks the specified mipmap level from a "segmented" CRN file. -// See the crnd_create_segmented_file() API below. -// Segmented files allow the user to control where the compressed mipmap data is stored. -bool crnd_unpack_level_segmented( - crnd_unpack_context pContext, - const void* pSrc, uint32 src_size_in_bytes, - void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, - uint32 level_index); - -// crnd_unpack_end() - Frees the decompress tables and unpacked palettes associated with the specified unpack context. -// Returns false if the context is NULL, or if it points to an invalid context. -// This function frees all memory associated with the context. -bool crnd_unpack_end(crnd_unpack_context pContext); - -// The following API's allow the user to create "segmented" CRN files. A segmented file contains multiple pieces: -// - Base data: Header + compression tables -// - Level data: Individual mipmap levels -// This allows mipmap levels from multiple CRN files to be tightly packed together into single files. - -// Returns a pointer to the level's compressed data, and optionally returns the level's compressed data size if pSize is not NULL. -const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize); - -// Returns the compressed size of the texture's header and compression tables (but no levels). -uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size); - -// Creates a "segmented" CRN texture from a normal CRN texture. The new texture will be created at pBase_data, and will be crnd_get_base_data_size() bytes long. -// base_data_size must be >= crnd_get_base_data_size(). -// The base data will contain the CRN header and compression tables, but no mipmap data. -bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size); - -} // namespace unitycrnd - -// Low-level CRN file header cracking. -namespace unitycrnd { -template -struct crn_packed_uint { - inline crn_packed_uint() {} - - inline crn_packed_uint(unsigned int val) { *this = val; } - - inline crn_packed_uint(const crn_packed_uint& other) { *this = other; } - - inline crn_packed_uint& operator=(const crn_packed_uint& rhs) { - if (this != &rhs) - memcpy(m_buf, rhs.m_buf, sizeof(m_buf)); - return *this; - } - - inline crn_packed_uint& operator=(unsigned int val) { - //CRND_ASSERT((N == 4U) || (val < (1U << (N * 8U)))); - - val <<= (8U * (4U - N)); - - for (unsigned int i = 0; i < N; i++) { - m_buf[i] = static_cast(val >> 24U); - val <<= 8U; - } - - return *this; - } - - inline operator unsigned int() const { - switch (N) { - case 1: - return m_buf[0]; - case 2: - return (m_buf[0] << 8U) | m_buf[1]; - case 3: - return (m_buf[0] << 16U) | (m_buf[1] << 8U) | (m_buf[2]); - default: - return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]); - } - } - - unsigned char m_buf[N]; -}; - -#pragma pack(push) -#pragma pack(1) -struct crn_palette { - crn_packed_uint<3> m_ofs; - crn_packed_uint<3> m_size; - crn_packed_uint<2> m_num; -}; - -enum crn_header_flags { - // If set, the compressed mipmap level data is not located after the file's base data - it will be separately managed by the user instead. - cCRNHeaderFlagSegmented = 1 -}; - -struct crn_header { - enum { cCRNSigValue = ('H' << 8) | 'x' }; - - crn_packed_uint<2> m_sig; - crn_packed_uint<2> m_header_size; - crn_packed_uint<2> m_header_crc16; - - crn_packed_uint<4> m_data_size; - crn_packed_uint<2> m_data_crc16; - - crn_packed_uint<2> m_width; - crn_packed_uint<2> m_height; - - crn_packed_uint<1> m_levels; - crn_packed_uint<1> m_faces; - - crn_packed_uint<1> m_format; - crn_packed_uint<2> m_flags; - - crn_packed_uint<4> m_reserved; - crn_packed_uint<4> m_userdata0; - crn_packed_uint<4> m_userdata1; - - crn_palette m_color_endpoints; - crn_palette m_color_selectors; - - crn_palette m_alpha_endpoints; - crn_palette m_alpha_selectors; - - crn_packed_uint<2> m_tables_size; - crn_packed_uint<3> m_tables_ofs; - - // m_level_ofs[] is actually an array of offsets: m_level_ofs[m_levels] - crn_packed_uint<4> m_level_ofs[1]; -}; - -const unsigned int cCRNHeaderMinSize = 62U; - -#pragma pack(pop) - -} // namespace unitycrnd - -#endif // CRND_INCLUDE_CRN_DEFS_H diff --git a/Texture2DDecoderNative/unitycrunch/crnlib.h b/Texture2DDecoderNative/unitycrunch/crnlib.h deleted file mode 100644 index d1186d5..0000000 --- a/Texture2DDecoderNative/unitycrunch/crnlib.h +++ /dev/null @@ -1,640 +0,0 @@ -// File: crnlib.h - Advanced DXTn texture compression library. -// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC -// See copyright notice and license at the end of this file. -// -// This header file contains the public crnlib declarations for DXTn, -// clustered DXTn, and CRN compression/decompression. -// -// Note: This library does NOT need to be linked into your game executable if -// all you want to do is transcode .CRN files to raw DXTn bits at run-time. -// The crn_decomp.h header file library contains all the code necessary for -// decompression. -// -// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing -#ifndef CRNLIB_H -#define CRNLIB_H - -#ifdef _MSC_VER -#pragma warning(disable : 4127) // conditional expression is constant -#endif - -#define CRNLIB_VERSION 104 - -#define CRNLIB_SUPPORT_ATI_COMPRESS 0 -#define CRNLIB_SUPPORT_SQUISH 0 - -typedef unsigned char crn_uint8; -typedef unsigned short crn_uint16; -typedef unsigned int crn_uint32; -typedef signed char crn_int8; -typedef signed short crn_int16; -typedef signed int crn_int32; -typedef unsigned int crn_bool; - -// crnlib can compress to these file types. -enum crn_file_type { - // .CRN - cCRNFileTypeCRN = 0, - - // .DDS using regular DXT or clustered DXT - cCRNFileTypeDDS, - - cCRNFileTypeForceDWORD = 0xFFFFFFFF -}; - -// Supported compressed pixel formats. -// Basically all the standard DX9 formats, with some swizzled DXT5 formats -// (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats. -enum crn_format { - cCRNFmtInvalid = -1, - - cCRNFmtDXT1 = 0, - - cCRNFmtFirstValid = cCRNFmtDXT1, - - // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS. - cCRNFmtDXT3, - - cCRNFmtDXT5, - - // Various DXT5 derivatives - cCRNFmtDXT5_CCxY, // Luma-chroma - cCRNFmtDXT5_xGxR, // Swizzled 2-component - cCRNFmtDXT5_xGBR, // Swizzled 3-component - cCRNFmtDXT5_AGBR, // Swizzled 4-component - - // ATI 3DC and X360 DXN - cCRNFmtDXN_XY, - cCRNFmtDXN_YX, - - // DXT5 alpha blocks only - cCRNFmtDXT5A, - - cCRNFmtETC1, - cCRNFmtETC2, - cCRNFmtETC2A, - cCRNFmtETC1S, - cCRNFmtETC2AS, - - cCRNFmtTotal, - - cCRNFmtForceDWORD = 0xFFFFFFFF -}; - -// Various library/file format limits. -enum crn_limits { - // Max. mipmap level resolution on any axis. - cCRNMaxLevelResolution = 4096, - - cCRNMinPaletteSize = 8, - cCRNMaxPaletteSize = 8192, - - cCRNMaxFaces = 6, - cCRNMaxLevels = 16, - - cCRNMaxHelperThreads = 15, - - cCRNMinQualityLevel = 0, - cCRNMaxQualityLevel = 255 -}; - -// CRN/DDS compression flags. -// See the m_flags member in the crn_comp_params struct, below. -enum crn_comp_flags { - // Enables perceptual colorspace distance metrics if set. - // Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps! - // Default: Set - cCRNCompFlagPerceptual = 1, - - // Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed. - // Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine - // where large macroblocks can be used without artifacts isn't perfect. - // Default: Set. - cCRNCompFlagHierarchical = 2, - - // cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews. - // Default: Not set. - cCRNCompFlagQuick = 4, - - // DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency. - // DXT5: OK to use both DXT5 block types. - // Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types. - // Default: Set. - cCRNCompFlagUseBothBlockTypes = 8, - - // OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha). - // Currently only used when writing to .DDS files, .CRN never uses alpha blocks. - // Default: Not set. - cCRNCompFlagUseTransparentIndicesForBlack = 16, - - // Disables endpoint caching, for more deterministic output. - // Currently only used when writing to .DDS files. - // Default: Not set. - cCRNCompFlagDisableEndpointCaching = 32, - - // If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files. - // Default: Not set. - cCRNCompFlagManualPaletteSizes = 64, - - // If enabled, DXT1A alpha blocks are used to encode single bit transparency. - // Default: Not set. - cCRNCompFlagDXT1AForTransparency = 128, - - // If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr). - // This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks - // with some chroma present if doing so will ultimately lead to lower luma error). - // Only enable on grayscale source images. - // Default: Not set. - cCRNCompFlagGrayscaleSampling = 256, - - // If enabled, debug information will be output during compression. - // Default: Not set. - cCRNCompFlagDebugging = 0x80000000, - - cCRNCompFlagForceDWORD = 0xFFFFFFFF -}; - -// Controls DXTn quality vs. speed control - only used when compressing to .DDS. -enum crn_dxt_quality { - cCRNDXTQualitySuperFast, - cCRNDXTQualityFast, - cCRNDXTQualityNormal, - cCRNDXTQualityBetter, - cCRNDXTQualityUber, - - cCRNDXTQualityTotal, - - cCRNDXTQualityForceDWORD = 0xFFFFFFFF -}; - -// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS. -enum crn_dxt_compressor_type { - cCRNDXTCompressorCRN, // Use crnlib's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and crnlib's ETC1 is a lot fasterw with similiar quality to Erricson's) - cCRNDXTCompressorCRNF, // Use crnlib's "fast" DXTc block compressor - cCRNDXTCompressorRYG, // Use RYG's DXTc block compressor (low quality, but very fast) - -#if CRNLIB_SUPPORT_ATI_COMPRESS - cCRNDXTCompressorATI, -#endif - -#if CRNLIB_SUPPORT_SQUISH - cCRNDXTCompressorSquish, -#endif - - cCRNTotalDXTCompressors, - - cCRNDXTCompressorForceDWORD = 0xFFFFFFFF -}; - -// Progress callback function. -// Processing will stop prematurely (and fail) if the callback returns false. -// phase_index, total_phases - high level progress -// subphase_index, total_subphases - progress within current phase -typedef crn_bool (*crn_progress_callback_func)(crn_uint32 phase_index, crn_uint32 total_phases, crn_uint32 subphase_index, crn_uint32 total_subphases, void* pUser_data_ptr); - -// CRN/DDS compression parameters struct. -struct crn_comp_params { - inline crn_comp_params() { clear(); } - - // Clear struct to default parameters. - inline void clear() { - m_size_of_obj = sizeof(*this); - m_file_type = cCRNFileTypeCRN; - m_faces = 1; - m_width = 0; - m_height = 0; - m_levels = 1; - m_format = cCRNFmtDXT1; - m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes; - - for (crn_uint32 f = 0; f < cCRNMaxFaces; f++) - for (crn_uint32 l = 0; l < cCRNMaxLevels; l++) - m_pImages[f][l] = NULL; - - m_target_bitrate = 0.0f; - m_quality_level = cCRNMaxQualityLevel; - m_dxt1a_alpha_threshold = 128; - m_dxt_quality = cCRNDXTQualityUber; - m_dxt_compressor_type = cCRNDXTCompressorCRN; - m_alpha_component = 3; - - m_crn_adaptive_tile_color_psnr_derating = 2.0f; - m_crn_adaptive_tile_alpha_psnr_derating = 2.0f; - m_crn_color_endpoint_palette_size = 0; - m_crn_color_selector_palette_size = 0; - m_crn_alpha_endpoint_palette_size = 0; - m_crn_alpha_selector_palette_size = 0; - - m_num_helper_threads = 0; - m_userdata0 = 0; - m_userdata1 = 0; - m_pProgress_func = NULL; - m_pProgress_func_data = NULL; - } - - inline bool operator==(const crn_comp_params& rhs) const { -#define CRNLIB_COMP(x) \ - do { \ - if ((x) != (rhs.x)) \ - return false; \ - } while (0) - CRNLIB_COMP(m_size_of_obj); - CRNLIB_COMP(m_file_type); - CRNLIB_COMP(m_faces); - CRNLIB_COMP(m_width); - CRNLIB_COMP(m_height); - CRNLIB_COMP(m_levels); - CRNLIB_COMP(m_format); - CRNLIB_COMP(m_flags); - CRNLIB_COMP(m_target_bitrate); - CRNLIB_COMP(m_quality_level); - CRNLIB_COMP(m_dxt1a_alpha_threshold); - CRNLIB_COMP(m_dxt_quality); - CRNLIB_COMP(m_dxt_compressor_type); - CRNLIB_COMP(m_alpha_component); - CRNLIB_COMP(m_crn_adaptive_tile_color_psnr_derating); - CRNLIB_COMP(m_crn_adaptive_tile_alpha_psnr_derating); - CRNLIB_COMP(m_crn_color_endpoint_palette_size); - CRNLIB_COMP(m_crn_color_selector_palette_size); - CRNLIB_COMP(m_crn_alpha_endpoint_palette_size); - CRNLIB_COMP(m_crn_alpha_selector_palette_size); - CRNLIB_COMP(m_num_helper_threads); - CRNLIB_COMP(m_userdata0); - CRNLIB_COMP(m_userdata1); - CRNLIB_COMP(m_pProgress_func); - CRNLIB_COMP(m_pProgress_func_data); - - for (crn_uint32 f = 0; f < cCRNMaxFaces; f++) - for (crn_uint32 l = 0; l < cCRNMaxLevels; l++) - CRNLIB_COMP(m_pImages[f][l]); - -#undef CRNLIB_COMP - return true; - } - - // Returns true if the input parameters are reasonable. - inline bool check() const { - if ((m_file_type > cCRNFileTypeDDS) || - (((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) || - (m_dxt1a_alpha_threshold > 255) || - ((m_faces != 1) && (m_faces != 6)) || - ((m_width < 1) || (m_width > cCRNMaxLevelResolution)) || - ((m_height < 1) || (m_height > cCRNMaxLevelResolution)) || - ((m_levels < 1) || (m_levels > cCRNMaxLevels)) || - ((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) || - ((m_crn_color_endpoint_palette_size) && ((m_crn_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_color_endpoint_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_color_selector_palette_size) && ((m_crn_color_selector_palette_size < cCRNMinPaletteSize) || (m_crn_color_selector_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_alpha_endpoint_palette_size) && ((m_crn_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) || - ((m_crn_alpha_selector_palette_size) && ((m_crn_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_selector_palette_size > cCRNMaxPaletteSize))) || - (m_alpha_component > 3) || - (m_num_helper_threads > cCRNMaxHelperThreads) || - (m_dxt_quality > cCRNDXTQualityUber) || - (m_dxt_compressor_type >= cCRNTotalDXTCompressors)) { - return false; - } - return true; - } - - // Helper to set/get flags from m_flags member. - inline bool get_flag(crn_comp_flags flag) const { return (m_flags & flag) != 0; } - inline void set_flag(crn_comp_flags flag, bool val) { - m_flags &= ~flag; - if (val) - m_flags |= flag; - } - - crn_uint32 m_size_of_obj; - - crn_file_type m_file_type; // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS. - - crn_uint32 m_faces; // 1 (2D map) or 6 (cubemap) - crn_uint32 m_width; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - crn_uint32 m_height; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - crn_uint32 m_levels; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK - - crn_format m_format; // Output pixel format. - - crn_uint32 m_flags; // see crn_comp_flags enum - - // Array of pointers to 32bpp input images. - const crn_uint32* m_pImages[cCRNMaxFaces][cCRNMaxLevels]; - - // Target bitrate - if non-zero, the compressor will use an interpolative search to find the - // highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll - // try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow. - float m_target_bitrate; - - // Desired quality level. - // Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint. - crn_uint32 m_quality_level; // [cCRNMinQualityLevel, cCRNMaxQualityLevel] - - // DXTn compression parameters. - crn_uint32 m_dxt1a_alpha_threshold; - crn_dxt_quality m_dxt_quality; - crn_dxt_compressor_type m_dxt_compressor_type; - - // Alpha channel's component. Defaults to 3. - crn_uint32 m_alpha_component; - - // Various low-level CRN specific parameters. - float m_crn_adaptive_tile_color_psnr_derating; - float m_crn_adaptive_tile_alpha_psnr_derating; - - crn_uint32 m_crn_color_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - crn_uint32 m_crn_color_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - - crn_uint32 m_crn_alpha_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - crn_uint32 m_crn_alpha_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize] - - // Number of helper threads to create during compression. 0=no threading. - crn_uint32 m_num_helper_threads; - - // CRN userdata0 and userdata1 members, which are written directly to the header of the output file. - crn_uint32 m_userdata0; - crn_uint32 m_userdata1; - - // User provided progress callback. - crn_progress_callback_func m_pProgress_func; - void* m_pProgress_func_data; -}; - -// Mipmap generator's mode. -enum crn_mip_mode { - cCRNMipModeUseSourceOrGenerateMips, // Use source texture's mipmaps if it has any, otherwise generate new mipmaps - cCRNMipModeUseSourceMips, // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps - cCRNMipModeGenerateMips, // Always generate new mipmaps - cCRNMipModeNoMips, // Output texture has no mipmaps - - cCRNMipModeTotal, - - cCRNModeForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_mip_mode_desc(crn_mip_mode m); -const char* crn_get_mip_mode_name(crn_mip_mode m); - -// Mipmap generator's filter kernel. -enum crn_mip_filter { - cCRNMipFilterBox, - cCRNMipFilterTent, - cCRNMipFilterLanczos4, - cCRNMipFilterMitchell, - cCRNMipFilterKaiser, // Kaiser=default mipmap filter - - cCRNMipFilterTotal, - - cCRNMipFilterForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_mip_filter_name(crn_mip_filter f); - -// Mipmap generator's scale mode. -enum crn_scale_mode { - cCRNSMDisabled, - cCRNSMAbsolute, - cCRNSMRelative, - cCRNSMLowerPow2, - cCRNSMNearestPow2, - cCRNSMNextPow2, - - cCRNSMTotal, - - cCRNSMForceDWORD = 0xFFFFFFFF -}; - -const char* crn_get_scale_mode_desc(crn_scale_mode sm); - -// Mipmap generator parameters. -struct crn_mipmap_params { - inline crn_mipmap_params() { clear(); } - - inline void clear() { - m_size_of_obj = sizeof(*this); - m_mode = cCRNMipModeUseSourceOrGenerateMips; - m_filter = cCRNMipFilterKaiser; - m_gamma_filtering = true; - m_gamma = 2.2f; - // Default "blurriness" factor of .9 actually sharpens the output a little. - m_blurriness = .9f; - m_renormalize = false; - m_tiled = false; - m_max_levels = cCRNMaxLevels; - m_min_mip_size = 1; - - m_scale_mode = cCRNSMDisabled; - m_scale_x = 1.0f; - m_scale_y = 1.0f; - - m_window_left = 0; - m_window_top = 0; - m_window_right = 0; - m_window_bottom = 0; - - m_clamp_scale = false; - m_clamp_width = 0; - m_clamp_height = 0; - } - - inline bool check() const { return true; } - - inline bool operator==(const crn_mipmap_params& rhs) const { -#define CRNLIB_COMP(x) \ - do { \ - if ((x) != (rhs.x)) \ - return false; \ - } while (0) - CRNLIB_COMP(m_size_of_obj); - CRNLIB_COMP(m_mode); - CRNLIB_COMP(m_filter); - CRNLIB_COMP(m_gamma_filtering); - CRNLIB_COMP(m_gamma); - CRNLIB_COMP(m_blurriness); - CRNLIB_COMP(m_renormalize); - CRNLIB_COMP(m_tiled); - CRNLIB_COMP(m_max_levels); - CRNLIB_COMP(m_min_mip_size); - CRNLIB_COMP(m_scale_mode); - CRNLIB_COMP(m_scale_x); - CRNLIB_COMP(m_scale_y); - CRNLIB_COMP(m_window_left); - CRNLIB_COMP(m_window_top); - CRNLIB_COMP(m_window_right); - CRNLIB_COMP(m_window_bottom); - CRNLIB_COMP(m_clamp_scale); - CRNLIB_COMP(m_clamp_width); - CRNLIB_COMP(m_clamp_height); - return true; -#undef CRNLIB_COMP - } - crn_uint32 m_size_of_obj; - - crn_mip_mode m_mode; - crn_mip_filter m_filter; - - crn_bool m_gamma_filtering; - float m_gamma; - - float m_blurriness; - - crn_uint32 m_max_levels; - crn_uint32 m_min_mip_size; - - crn_bool m_renormalize; - crn_bool m_tiled; - - crn_scale_mode m_scale_mode; - float m_scale_x; - float m_scale_y; - - crn_uint32 m_window_left; - crn_uint32 m_window_top; - crn_uint32 m_window_right; - crn_uint32 m_window_bottom; - - crn_bool m_clamp_scale; - crn_uint32 m_clamp_width; - crn_uint32 m_clamp_height; -}; - -// -------- High-level helper function definitions for CDN/DDS compression. - -#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT -#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2 -#endif - -// Function to set an optional user provided memory allocation/reallocation/msize routines. -// By default, crnlib just uses malloc(), free(), etc. for all allocations. -typedef void* (*crn_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data); -typedef size_t (*crn_msize_func)(void* p, void* pUser_data); -void crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data); - -// Frees memory blocks allocated by crn_compress(), crn_decompress_crn_to_dds(), or crn_decompress_dds_to_images(). -void crn_free_block(void* pBlock); - -// Compresses a 32-bit/pixel texture to either: a regular DX9 DDS file, a "clustered" (or reduced entropy) DX9 DDS file, or a CRN file in memory. -// Input parameters: -// comp_params is the compression parameters struct, defined above. -// compressed_size will be set to the size of the returned memory block containing the output file. -// The returned block must be freed by calling crn_free_block(). -// *pActual_quality_level will be set to the actual quality level used to compress the image. May be NULL. -// *pActual_bitrate will be set to the output file's effective bitrate, possibly taking into account LZMA compression. May be NULL. -// Return value: -// The compressed file data, or NULL on failure. -// compressed_size will be set to the size of the returned memory buffer. -// Notes: -// A "regular" DDS file is compressed using normal DXTn compression at the specified DXT quality level. -// A "clustered" DDS file is compressed using clustered DXTn compression to either the target bitrate or the specified integer quality factor. -// The output file is a standard DX9 format DDS file, except the compressor assumes you will be later losslessly compressing the DDS output file using the LZMA algorithm. -// A texture is defined as an array of 1 or 6 "faces" (6 faces=cubemap), where each "face" consists of between [1,cCRNMaxLevels] mipmap levels. -// Mipmap levels are simple 32-bit 2D images with a pitch of width*sizeof(uint32), arranged in the usual raster order (top scanline first). -// The image pixels may be grayscale (YYYX bytes in memory), grayscale/alpha (YYYA in memory), 24-bit (RGBX in memory), or 32-bit (RGBA) colors (where "X"=don't care). -// RGB color data is generally assumed to be in the sRGB colorspace. If not, be sure to clear the "cCRNCompFlagPerceptual" in the crn_comp_params struct! -void* crn_compress(const crn_comp_params& comp_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL); - -// Like the above function, except this function can also do things like generate mipmaps, and resize or crop the input texture before compression. -// The actual operations performed are controlled by the crn_mipmap_params struct members. -// Be sure to set the "m_gamma_filtering" member of crn_mipmap_params to false if the input texture is not sRGB. -void* crn_compress(const crn_comp_params& comp_params, const crn_mipmap_params& mip_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL); - -// Transcodes an entire CRN file to DDS using the crn_decomp.h header file library to do most of the heavy lifting. -// The output DDS file's format is guaranteed to be one of the DXTn formats in the crn_format enum. -// This is a fast operation, because the CRN format is explicitly designed to be efficiently transcodable to DXTn. -// For more control over decompression, see the lower-level helper functions in crn_decomp.h, which do not depend at all on crnlib. -void* crn_decompress_crn_to_dds(const void* pCRN_file_data, crn_uint32& file_size); - -// Decompresses an entire DDS file in any supported format to uncompressed 32-bit/pixel image(s). -// See the crnlib::pixel_format enum in inc/dds_defs.h for a list of the supported DDS formats. -// You are responsible for freeing each image block, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer. -struct crn_texture_desc { - crn_uint32 m_faces; - crn_uint32 m_width; - crn_uint32 m_height; - crn_uint32 m_levels; - crn_uint32 m_fmt_fourcc; // Same as crnlib::pixel_format -}; -bool crn_decompress_dds_to_images(const void* pDDS_file_data, crn_uint32 dds_file_size, crn_uint32** ppImages, crn_texture_desc& tex_desc); - -// Frees all images allocated by crn_decompress_dds_to_images(). -void crn_free_all_images(crn_uint32** ppImages, const crn_texture_desc& desc); - -// -------- crn_format related helpers functions. - -// Returns the FOURCC format equivalent to the specified crn_format. -crn_uint32 crn_get_format_fourcc(crn_format fmt); - -// Returns the crn_format's bits per texel. -crn_uint32 crn_get_format_bits_per_texel(crn_format fmt); - -// Returns the crn_format's number of bytes per block. -crn_uint32 crn_get_bytes_per_dxt_block(crn_format fmt); - -// Returns the non-swizzled, basic DXTn version of the specified crn_format. -// This is the format you would supply D3D or OpenGL. -crn_format crn_get_fundamental_dxt_format(crn_format fmt); - -// -------- String helpers. - -// Converts a crn_file_type to a string. -const char* crn_get_file_type_ext(crn_file_type file_type); - -// Converts a crn_format to a string. -const char* crn_get_format_string(crn_format fmt); - -// Converts a crn_dxt_quality to a string. -const char* crn_get_dxt_quality_string(crn_dxt_quality q); - -// -------- Low-level DXTn 4x4 block compressor API - -// crnlib's DXTn endpoint optimizer actually supports any number of source pixels (i.e. from 1 to thousands, not just 16), -// but for simplicity this API only supports 4x4 texel blocks. -typedef void* crn_block_compressor_context_t; - -// Create a DXTn block compressor. -// This function only supports the basic/nonswizzled "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX. -// Avoid calling this multiple times if you intend on compressing many blocks, because it allocates some memory. -crn_block_compressor_context_t crn_create_block_compressor(const crn_comp_params& params); - -// Compresses a block of 16 pixels to the destination DXTn block. -// pDst_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others). -// pPixels should be an array of 16 crn_uint32's. Each crn_uint32 must be r,g,b,a (r is always first) in memory. -void crn_compress_block(crn_block_compressor_context_t pContext, const crn_uint32* pPixels, void* pDst_block); - -// Frees a DXTn block compressor. -void crn_free_block_compressor(crn_block_compressor_context_t pContext); - -// Unpacks a compressed block to pDst_pixels. -// pSrc_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others). -// pDst_pixel should be an array of 16 crn_uint32's. Each uint32 will be r,g,b,a (r is always first) in memory. -// crn_fmt should be one of the "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX. -// The various swizzled DXT5 formats (such as cCRNFmtDXT5_xGBR, etc.) will be unpacked as if they where plain DXT5. -// Returns false if the crn_fmt is invalid. -bool crn_decompress_block(const void* pSrc_block, crn_uint32* pDst_pixels, crn_format crn_fmt); - -#endif // CRNLIB_H - -//------------------------------------------------------------------------------ -// -// crnlib uses the ZLIB license: -// http://opensource.org/licenses/Zlib -// -// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//------------------------------------------------------------------------------ diff --git a/Texture2DDecoderWrapper/T2DDll.cs b/Texture2DDecoderWrapper/T2DDll.cs deleted file mode 100644 index 834d490..0000000 --- a/Texture2DDecoderWrapper/T2DDll.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Texture2DDecoder -{ - internal static class T2DDll - { - - internal const string DllName = "Texture2DDecoderNative"; - - } -} diff --git a/Texture2DDecoderWrapper/Texture2DDecoderWrapper.csproj b/Texture2DDecoderWrapper/Texture2DDecoderWrapper.csproj deleted file mode 100644 index b1e6699..0000000 --- a/Texture2DDecoderWrapper/Texture2DDecoderWrapper.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net6.0 - true - 0.18.60 - 0.18.60 - 0.18.60 - Copyright © Perfare 2020-2022; Copyright © hozuki 2020 - embedded - - - - - - - diff --git a/Texture2DDecoderWrapper/TextureDecoder.PInvoke.cs b/Texture2DDecoderWrapper/TextureDecoder.PInvoke.cs deleted file mode 100644 index 8fcf30f..0000000 --- a/Texture2DDecoderWrapper/TextureDecoder.PInvoke.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Texture2DDecoder -{ - unsafe partial class TextureDecoder - { - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeDXT1(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeDXT5(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodePVRTC(void* data, int width, int height, void* image, [MarshalAs(UnmanagedType.Bool)] bool is2bpp); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeETC1(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeETC2(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeETC2A1(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeETC2A8(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeEACR(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeEACRSigned(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeEACRG(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeEACRGSigned(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeBC4(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeBC5(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeBC6(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeBC7(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeATCRGB4(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeATCRGBA8(void* data, int width, int height, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DecodeASTC(void* data, int width, int height, int blockWidth, int blockHeight, void* image); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void DisposeBuffer(ref void* ppBuffer); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void UnpackCrunch(void* data, uint dataSize, out void* result, out uint resultSize); - - [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void UnpackUnityCrunch(void* data, uint dataSize, out void* result, out uint resultSize); - - } -} diff --git a/Texture2DDecoderWrapper/TextureDecoder.cs b/Texture2DDecoderWrapper/TextureDecoder.cs deleted file mode 100644 index 797b78f..0000000 --- a/Texture2DDecoderWrapper/TextureDecoder.cs +++ /dev/null @@ -1,262 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using AssetStudio.PInvoke; - -namespace Texture2DDecoder -{ - public static unsafe partial class TextureDecoder - { - - static TextureDecoder() - { - DllLoader.PreloadDll(T2DDll.DllName); - } - - public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeDXT1(pData, width, height, pImage); - } - } - } - - public static bool DecodeDXT5(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeDXT5(pData, width, height, pImage); - } - } - } - - public static bool DecodePVRTC(byte[] data, int width, int height, byte[] image, bool is2bpp) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodePVRTC(pData, width, height, pImage, is2bpp); - } - } - } - - public static bool DecodeETC1(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeETC1(pData, width, height, pImage); - } - } - } - - public static bool DecodeETC2(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeETC2(pData, width, height, pImage); - } - } - } - - public static bool DecodeETC2A1(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeETC2A1(pData, width, height, pImage); - } - } - } - - public static bool DecodeETC2A8(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeETC2A8(pData, width, height, pImage); - } - } - } - - public static bool DecodeEACR(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeEACR(pData, width, height, pImage); - } - } - } - - public static bool DecodeEACRSigned(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeEACRSigned(pData, width, height, pImage); - } - } - } - - public static bool DecodeEACRG(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeEACRG(pData, width, height, pImage); - } - } - } - - public static bool DecodeEACRGSigned(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeEACRGSigned(pData, width, height, pImage); - } - } - } - - public static bool DecodeBC4(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeBC4(pData, width, height, pImage); - } - } - } - - public static bool DecodeBC5(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeBC5(pData, width, height, pImage); - } - } - } - - public static bool DecodeBC6(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeBC6(pData, width, height, pImage); - } - } - } - - public static bool DecodeBC7(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeBC7(pData, width, height, pImage); - } - } - } - - public static bool DecodeATCRGB4(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeATCRGB4(pData, width, height, pImage); - } - } - } - - public static bool DecodeATCRGBA8(byte[] data, int width, int height, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeATCRGBA8(pData, width, height, pImage); - } - } - } - - public static bool DecodeASTC(byte[] data, int width, int height, int blockWidth, int blockHeight, byte[] image) - { - fixed (byte* pData = data) - { - fixed (byte* pImage = image) - { - return DecodeASTC(pData, width, height, blockWidth, blockHeight, pImage); - } - } - } - - public static byte[] UnpackCrunch(byte[] data) - { - void* pBuffer; - uint bufferSize; - - fixed (byte* pData = data) - { - UnpackCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize); - } - - if (pBuffer == null) - { - return null; - } - - var result = new byte[bufferSize]; - - Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize); - - DisposeBuffer(ref pBuffer); - - return result; - } - - public static byte[] UnpackUnityCrunch(byte[] data) - { - void* pBuffer; - uint bufferSize; - - fixed (byte* pData = data) - { - UnpackUnityCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize); - } - - if (pBuffer == null) - { - return null; - } - - var result = new byte[bufferSize]; - - Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize); - - DisposeBuffer(ref pBuffer); - - return result; - } - - } -}