diff --git a/File_Format_Library/FileFormats/Archives/GFPAK.cs b/File_Format_Library/FileFormats/Archives/GFPAK.cs index b5fc795e..cf95f2b1 100644 --- a/File_Format_Library/FileFormats/Archives/GFPAK.cs +++ b/File_Format_Library/FileFormats/Archives/GFPAK.cs @@ -493,6 +493,11 @@ namespace FirstPlugin public void Save(System.IO.Stream stream) { + if (version == 0x1000 && !File.Exists($"{Runtime.ExecutableDir}\\oo2core_6_win64.dll")) + { + MessageBox.Show("It is necessary to have 'oo2core_6_win64.dll' in the executable folder."); + return; + } Write(new FileWriter(stream)); } @@ -544,6 +549,13 @@ namespace FirstPlugin GFPAKHashCache.EnsureHashCache(); version = reader.ReadInt32(); + + if (version == 0x1000 && !File.Exists($"{Runtime.ExecutableDir}\\oo2core_6_win64.dll")) + { + MessageBox.Show("It is necessary to have 'oo2core_6_win64.dll' in the executable folder."); + return; + } + uint padding = reader.ReadUInt32(); uint FileCount = reader.ReadUInt32(); FolderCount = reader.ReadInt32(); @@ -582,7 +594,7 @@ namespace FirstPlugin fileEntry.Read(reader); string Extension = FindMatch(fileEntry.FileData); - if (Extension.EndsWith("gfbanmcfg")) + if (Extension.EndsWith("gfbanmcfg") && version != 0x1000) { GFBANMCFG cfg = new GFBANMCFG(); cfg.Load(new MemoryStream(fileEntry.FileData)); @@ -847,6 +859,11 @@ namespace FirstPlugin } else if (Type == CompressionType.None) FileData = reader.ReadBytes((int)DecompressedFileSize); + else if (Type == CompressionType.Oodle) + { + FileData = reader.ReadBytes((int)CompressedFileSize); + FileData = STLibraryCompression.Type_Oodle.Decompress(FileData, (int)DecompressedFileSize); + } else FileData = reader.ReadBytes((int)CompressedFileSize); } @@ -882,7 +899,8 @@ namespace FirstPlugin else if (Type == CompressionType.Zlib) return STLibraryCompression.ZLIB.Compress(data); else if (Type == CompressionType.Oodle) - throw new Exception("Oodle compression type not supported yet for saving!"); + return STLibraryCompression.Type_Oodle.Compress(data, Toolbox.Library.Compression.Oodle.OodleLZ_Compressor.OodleLZ_Compressor_Kraken, + Toolbox.Library.Compression.Oodle.OodleLZ_CompressionLevel.OodleLZ_CompressionLevel_Optimal2); else return data; } diff --git a/File_Format_Library/FileFormats/Hashes/GFPAKHashCache.cs b/File_Format_Library/FileFormats/Hashes/GFPAKHashCache.cs index 6e6da071..fe28b6a9 100644 --- a/File_Format_Library/FileFormats/Hashes/GFPAKHashCache.cs +++ b/File_Format_Library/FileFormats/Hashes/GFPAKHashCache.cs @@ -83,33 +83,61 @@ namespace FirstPlugin.FileFormats.Hashes PutHash(HashString); - if (HashString.Contains("pm0000") || - HashString.Contains("poke_XXXX") || - HashString.Contains("poke_ball_0000") || - HashString.Contains("poke_face_0000") || - HashString.Contains("poke_motion_0000")) + //Mon nums + if (HashString.Contains("XXXX")) { - GenerateGenericPokeStrings(HashString); + GeneratePkmnString(HashString); PokeHashTemplates.Add(HashString); } } } - private static void GenerateGenericPokeStrings(string hashStr) + private static void GeneratePkmnString(string hashStr) { - for (int i = 0; i < 1000; i++) - { - string pokeStr = string.Empty; - if (hashStr.Contains("pm0000")) pokeStr = hashStr.Replace("pm0000", $"pm{i.ToString("D4")}"); - else if (hashStr.Contains("poke_XXXX")) pokeStr = hashStr.Replace("poke_XXXX", $"poke_{i.ToString("D4")}"); - else if (hashStr.Contains("poke_ball_0000")) pokeStr = hashStr.Replace("poke_ball_0000", $"poke_ball_{i.ToString("D4")}"); - else if (hashStr.Contains("poke_face_0000")) pokeStr = hashStr.Replace("poke_face_0000", $"poke_face_{i.ToString("D4")}"); - else if (hashStr.Contains("poke_motion_0000")) pokeStr = hashStr.Replace("poke_motion_0000", $"poke_motion_{i.ToString("D4")}"); - ulong hash = FNV64A1.Calculate(pokeStr); - if (!HashCacheContent.ContainsKey(hash)) - HashCacheContent.Add(hash, pokeStr); - } + int[] alolanMons = { + 37, 38 + }; + int[] husuiMons = { + 58, 59, 100, 101, 157, 211, 215, 503, 549, 550, + 570, 571, 628, 751, 764, 765, 843, 1003, 1005, 1006 + }; + + int[] frenzyForms = { + 59, 101, 549, 751, 1002 + }; + + string pokeStr = string.Empty; + List monNames; + for (int i = 0; i < 1010; i++) + { + monNames = new List(); + //Gen species num + pokeStr = hashStr.Replace("XXXX", i.ToString("D4")); + + //..also sub out alt forms + if (frenzyForms.Contains(i)) + monNames.Add(pokeStr.Replace("YY", "71")); + + monNames.Add(pokeStr.Replace("YY", "00")); + + //..also sub out region forms + foreach (var n in monNames) { + if (alolanMons.Contains(i)) + TryAddHash(n.Replace("ZZ", "11")); + else if (husuiMons.Contains(i)) + TryAddHash(n.Replace("ZZ", "41")); + else + TryAddHash(n.Replace("ZZ", "00")); + } + monNames.Clear(); + } + } + + private static void TryAddHash(string str) { + ulong hash = FNV64A1.Calculate(str); + if (!HashCacheContent.ContainsKey(hash)) + HashCacheContent.Add(hash, str); } public static void GeneratePokeStringsFromFile(string FileName) diff --git a/File_Format_Library/FileFormats/NLG/LM3/LM3_Model.cs b/File_Format_Library/FileFormats/NLG/LM3/LM3_Model.cs index 365cff8a..32aa0727 100644 --- a/File_Format_Library/FileFormats/NLG/LM3/LM3_Model.cs +++ b/File_Format_Library/FileFormats/NLG/LM3/LM3_Model.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; @@ -63,7 +64,9 @@ namespace FirstPlugin.LuigisMansion3 settings.SuppressConfirmDialog = true; - DAE.Export($"{folderPath}/{mdl.Text}.dae", settings, model, new List()); + if (mdl.Text.Contains("/")) + Directory.CreateDirectory($"{folderPath}/{Path.GetDirectoryName(mdl.Text)}"); + DAE.Export($"{folderPath}/{mdl.Text.Replace("/", "//")}.dae", settings, model, new List()); } System.Windows.Forms.MessageBox.Show($"Exported models Successfuly!"); diff --git a/File_Format_Library/Resources/Hashes/Pkmn.txt b/File_Format_Library/Resources/Hashes/Pkmn.txt index b681424a..417ddf3b 100644 --- a/File_Format_Library/Resources/Hashes/Pkmn.txt +++ b/File_Format_Library/Resources/Hashes/Pkmn.txt @@ -1,110 +1,110 @@ pc0002_00_fa0004_eye_close01.gfbanm pc0002_00_fi0001_wait01_loop.gfbanm -bin/pokemon/pm0000_00/ -bin/pokemon/pm0000_00/tex/ -bin/pokemon/pm0000_00/anm/ -bin/pokemon/pm0000_00/mdl/ +bin/pokemon/pmXXXX_00/ +bin/pokemon/pmXXXX_00/tex/ +bin/pokemon/pmXXXX_00/anm/ +bin/pokemon/pmXXXX_00/mdl/ bin/pokemon_data/ bin/graphics/mask_texture/pattern_01/ bin/app/pokecamp/cooking/common_model/anm/ bin/app/pokecamp/cooking/common_model/mdl/ bin/app/pokecamp/cooking/common_model/ bin/chara/data/pc/p2/p1_base_app01/anm/ -pm0000_00.gfbpokecfg -pm0000_00.gfbmdl -pm0000_00_rare.gfbmdl -pm0000_00_field01.gfbanmcfg -pm0000_00_field.gfbanmcfg -pm0000_00_battle.gfbanmcfg -pm0000_00_capture.gfbanmcfg -pm0000_00_battle01.gfbanmcfg -pm0000_00_capture01.gfbanmcfg -pm0000_00_camp.gfbanmcfg -pm0000_00_app01.gfbanmcfg -pm0000_00_loop01.gfbanm -pm0000_00_loop02.gfbanm -pm0000_00_gloop01.gfbanm -pm0000_00_mouth01.gfbanm -pm0000_00_eye01.gfbanm -pm0000_00_ba01_land01.gfbanm -pm0000_00_ba01_landA01.gfbanm -pm0000_00_ba01_landB01.gfbanm -pm0000_00_ba01_landC01.gfbanm -pm0000_00_ba02_roar01.gfbanm -pm0000_00_ba10_waitA01.gfbanm -pm0000_00_ba10_waitA02.gfbanm -pm0000_00_ba10_waitB01.gfbanm -pm0000_00_ba10_waitB02.gfbanm -pm0000_00_ba10_waitC01.gfbanm -pm0000_00_ba10_waitC02.gfbanm -pm0000_00_ba20_buturi01.gfbanm -pm0000_00_ba20_buturi02.gfbanm -pm0000_00_ba20_buturi03.gfbanm -pm0000_00_ba21_tokusyu01.gfbanm -pm0000_00_ba21_tokusyu02.gfbanm -pm0000_00_ba21_tokusyu03.gfbanm -pm0000_00_ba30_damageS01.gfbanm -pm0000_00_ba41_down01.gfbanm -pm0000_00_ba50_wideuse01.gfbanm -pm0000_00_ba50_wideuse02.gfbanm -pm0000_00_ba50_wideuse03.gfbanm -pm0000_00_cm10_bawait_fiwait01.gfbanm -pm0000_00_cm10_bawait_kwwait01.gfbanm -pm0000_00_cm10_fiwait_bawait01.gfbanm -pm0000_00_cm10_fiwait_kwwait01.gfbanm -pm0000_00_cm10_kwwait_bawait01.gfbanm -pm0000_00_cm10_kwwait_fiwait01.gfbanm -pm0000_00_fi01_wait01.gfbanm -pm0000_00_fi01_wait02.gfbanm -pm0000_00_fi20_walk01.gfbanm -pm0000_00_fi21_run01.gfbanm -pm0000_00_fi30_wait_walk01.gfbanm -pm0000_00_fi30_walk_wait01.gfbanm -pm0000_00_fi31_run_wait01.gfbanm -pm0000_00_fi31_wait_run01.gfbanm -pm0000_00_fi32_run_walk01.gfbanm -pm0000_00_fi32_walk_run01.gfbanm -pm0000_00_fi50_conerwait01_start.gfbanm -pm0000_00_fi51_conerwait01_loop.gfbanm -pm0000_00_fi52_conerwait01_end.gfbanm -pm0000_00_fi70_threeselect01.gfbanm -pm0000_00_kw01_wait01.gfbanm -pm0000_00_kw10_respond01.gfbanm -pm0000_00_kw11_turnA01.gfbanm -pm0000_00_kw11_turnB01.gfbanm -pm0000_00_kw11_turnC01.gfbanm -pm0000_00_kw20_drowseA01.gfbanm -pm0000_00_kw20_drowseB01.gfbanm -pm0000_00_kw20_drowseC01.gfbanm -pm0000_00_kw21_sleepA01.gfbanm -pm0000_00_kw21_sleepB01.gfbanm -pm0000_00_kw21_sleepC01.gfbanm -pm0000_00_kw30_hate01.gfbanm -pm0000_00_kw30_hate02.gfbanm -pm0000_00_kw31_question01.gfbanm -pm0000_00_kw32_happyA01.gfbanm -pm0000_00_kw32_happyB01.gfbanm -pm0000_00_kw32_happyC01.gfbanm -pm0000_00_kw33_moveA01.gfbanm -pm0000_00_kw33_moveB01.gfbanm -pm0000_00_kw33_moveC01.gfbanm -pm0000_00_kw33_moveD01.gfbanm -pm0000_00_kw34_lonely01.gfbanm -pm0000_00_kw35_playA01.gfbanm -pm0000_00_kw35_playB01.gfbanm -pm0000_00_kw35_playC01.gfbanm -pm0000_00_kw36_mad01.gfbanm -pm0000_00_kw50_eatA01.gfbanm -pm0000_00_kw50_eatB01.gfbanm -pm0000_00_kw50_eatC01.gfbanm -pm0000_00_kw60_touch01.gfbanm +pmXXXX_00.gfbpokecfg +pmXXXX_00.gfbmdl +pmXXXX_00_rare.gfbmdl +pmXXXX_00_field01.gfbanmcfg +pmXXXX_00_field.gfbanmcfg +pmXXXX_00_battle.gfbanmcfg +pmXXXX_00_capture.gfbanmcfg +pmXXXX_00_battle01.gfbanmcfg +pmXXXX_00_capture01.gfbanmcfg +pmXXXX_00_camp.gfbanmcfg +pmXXXX_00_app01.gfbanmcfg +pmXXXX_00_loop01.gfbanm +pmXXXX_00_loop02.gfbanm +pmXXXX_00_gloop01.gfbanm +pmXXXX_00_mouth01.gfbanm +pmXXXX_00_eye01.gfbanm +pmXXXX_00_ba01_land01.gfbanm +pmXXXX_00_ba01_landA01.gfbanm +pmXXXX_00_ba01_landB01.gfbanm +pmXXXX_00_ba01_landC01.gfbanm +pmXXXX_00_ba02_roar01.gfbanm +pmXXXX_00_ba10_waitA01.gfbanm +pmXXXX_00_ba10_waitA02.gfbanm +pmXXXX_00_ba10_waitB01.gfbanm +pmXXXX_00_ba10_waitB02.gfbanm +pmXXXX_00_ba10_waitC01.gfbanm +pmXXXX_00_ba10_waitC02.gfbanm +pmXXXX_00_ba20_buturi01.gfbanm +pmXXXX_00_ba20_buturi02.gfbanm +pmXXXX_00_ba20_buturi03.gfbanm +pmXXXX_00_ba21_tokusyu01.gfbanm +pmXXXX_00_ba21_tokusyu02.gfbanm +pmXXXX_00_ba21_tokusyu03.gfbanm +pmXXXX_00_ba30_damageS01.gfbanm +pmXXXX_00_ba41_down01.gfbanm +pmXXXX_00_ba50_wideuse01.gfbanm +pmXXXX_00_ba50_wideuse02.gfbanm +pmXXXX_00_ba50_wideuse03.gfbanm +pmXXXX_00_cm10_bawait_fiwait01.gfbanm +pmXXXX_00_cm10_bawait_kwwait01.gfbanm +pmXXXX_00_cm10_fiwait_bawait01.gfbanm +pmXXXX_00_cm10_fiwait_kwwait01.gfbanm +pmXXXX_00_cm10_kwwait_bawait01.gfbanm +pmXXXX_00_cm10_kwwait_fiwait01.gfbanm +pmXXXX_00_fi01_wait01.gfbanm +pmXXXX_00_fi01_wait02.gfbanm +pmXXXX_00_fi20_walk01.gfbanm +pmXXXX_00_fi21_run01.gfbanm +pmXXXX_00_fi30_wait_walk01.gfbanm +pmXXXX_00_fi30_walk_wait01.gfbanm +pmXXXX_00_fi31_run_wait01.gfbanm +pmXXXX_00_fi31_wait_run01.gfbanm +pmXXXX_00_fi32_run_walk01.gfbanm +pmXXXX_00_fi32_walk_run01.gfbanm +pmXXXX_00_fi50_conerwait01_start.gfbanm +pmXXXX_00_fi51_conerwait01_loop.gfbanm +pmXXXX_00_fi52_conerwait01_end.gfbanm +pmXXXX_00_fi70_threeselect01.gfbanm +pmXXXX_00_kw01_wait01.gfbanm +pmXXXX_00_kw10_respond01.gfbanm +pmXXXX_00_kw11_turnA01.gfbanm +pmXXXX_00_kw11_turnB01.gfbanm +pmXXXX_00_kw11_turnC01.gfbanm +pmXXXX_00_kw20_drowseA01.gfbanm +pmXXXX_00_kw20_drowseB01.gfbanm +pmXXXX_00_kw20_drowseC01.gfbanm +pmXXXX_00_kw21_sleepA01.gfbanm +pmXXXX_00_kw21_sleepB01.gfbanm +pmXXXX_00_kw21_sleepC01.gfbanm +pmXXXX_00_kw30_hate01.gfbanm +pmXXXX_00_kw30_hate02.gfbanm +pmXXXX_00_kw31_question01.gfbanm +pmXXXX_00_kw32_happyA01.gfbanm +pmXXXX_00_kw32_happyB01.gfbanm +pmXXXX_00_kw32_happyC01.gfbanm +pmXXXX_00_kw33_moveA01.gfbanm +pmXXXX_00_kw33_moveB01.gfbanm +pmXXXX_00_kw33_moveC01.gfbanm +pmXXXX_00_kw33_moveD01.gfbanm +pmXXXX_00_kw34_lonely01.gfbanm +pmXXXX_00_kw35_playA01.gfbanm +pmXXXX_00_kw35_playB01.gfbanm +pmXXXX_00_kw35_playC01.gfbanm +pmXXXX_00_kw36_mad01.gfbanm +pmXXXX_00_kw50_eatA01.gfbanm +pmXXXX_00_kw50_eatB01.gfbanm +pmXXXX_00_kw50_eatC01.gfbanm +pmXXXX_00_kw60_touch01.gfbanm bin/chara/data/pc/p1/anm bin/chara/data/pc/p1/mdl bin/archive/chara/data/pc/p1/anm bin/archive/chara/data/pc/p1/mdl -bin/pokemon/pm0000_00/g_shader/ -pm0000_00.gfbgpokecfg +bin/pokemon/pmXXXX_00/g_shader/ +pmXXXX_00.gfbgpokecfg eg_cmn_cloud01.gfbanm eg_cmn_cloud01.gfbanmcfg eg_cmn_cloud01.gfbmdl @@ -4438,4 +4438,29 @@ ob0003_30_ba0006_luminous06.gfbanm ob0003_30_ba0007_luminous07.gfbanm ob0003_30_ba0008_luminous08.gfbanm ob0023_00_fi0002_shine01.gfbanm -ob0023_00_fi0001_wait01_loop.gfbanm \ No newline at end of file +ob0023_00_fi0001_wait01_loop.gfbanm +bin/pokemon/pmXXXX/pmXXXX_YY_ZZ/ +bin/pokemon/pmXXXX/pmXXXX_YY_ZZ/anm/ +bin/pokemon/pmXXXX/pmXXXX_YY_ZZ/mdl/ +bin/pokemon/pmXXXX/pmXXXX_YY_ZZ/tex/ +bin/pokemon/pmXXXX/pmXXXX_YY_ZZ/locators/ +pmXXXX_YY_ZZ.trpokecfg +pmXXXX_YY_ZZ.trmdl +pmXXXX_YY_ZZ.trmtr +pmXXXX_YY_ZZ.trmsh +pmXXXX_YY_ZZ.trmbf +pmXXXX_YY_ZZ.trmmt +pmXXXX_YY_ZZ.trskl +pmXXXX_YY_ZZ_eff.trskl +pmXXXX_YY_ZZ_rare.trmtr +pmXXXX_YY_ZZ_lod1.trmbf +pmXXXX_YY_ZZ_lod1.trmsh +pmXXXX_YY_ZZ_lod2.trmbf +pmXXXX_YY_ZZ_lod2.trmsh +pmXXXX_YY_ZZ_base.tracn +pmXXXX_YY_ZZ_base.tracp +pmXXXX_YY_ZZ_base.tracr +pmXXXX_YY_ZZ_base.tracs +pmXXXX_YY_ZZ_base.tracl +pmXXXX_YY_ZZ_base.tralk +pmXXXX_YY_ZZ_base.trbik \ No newline at end of file diff --git a/Switch_Toolbox_Library/Compression/Oodle.cs b/Switch_Toolbox_Library/Compression/Oodle.cs new file mode 100644 index 00000000..3560e3cf --- /dev/null +++ b/Switch_Toolbox_Library/Compression/Oodle.cs @@ -0,0 +1,245 @@ +using System; +using System.Runtime.InteropServices; + +namespace Toolbox.Library.Compression +{ + // Code from https://github.com/JKAnderson/SoulsFormats/blob/master/SoulsFormats/Util/Oodle26.cs + public static class Oodle + { + public static byte[] Compress(byte[] source, OodleLZ_Compressor compressor, OodleLZ_CompressionLevel level) + { + IntPtr pOptions = OodleLZ_CompressOptions_GetDefault(compressor, level); + OodleLZ_CompressOptions options = Marshal.PtrToStructure(pOptions); + // Required for the game to not crash + options.seekChunkReset = true; + // This is already the default but I am including it for authenticity to game code + options.seekChunkLen = 0x40000; + pOptions = Marshal.AllocHGlobal(Marshal.SizeOf()); + + try + { + Marshal.StructureToPtr(options, pOptions, false); + long compressedBufferSizeNeeded = OodleLZ_GetCompressedBufferSizeNeeded(source.LongLength); + byte[] compBuf = new byte[compressedBufferSizeNeeded]; + long compLen = OodleLZ_Compress(compressor, source, source.LongLength, compBuf, level, pOptions, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0); + Array.Resize(ref compBuf, (int)compLen); + return compBuf; + } + finally + { + Marshal.FreeHGlobal(pOptions); + } + } + + public static byte[] Decompress(byte[] source, long uncompressedSize) + { + long decodeBufferSize = OodleLZ_GetDecodeBufferSize(uncompressedSize, true); + byte[] rawBuf = new byte[decodeBufferSize]; + long rawLen = OodleLZ_Decompress(source, source.LongLength, rawBuf, uncompressedSize); + Array.Resize(ref rawBuf, (int)rawLen); + return rawBuf; + } + + + /// + /// + /// + /// + /// + /// = NULL + /// = NULL + /// = NULL + /// = NULL + /// = 0 + [DllImport("oo2core_6_win64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern long OodleLZ_Compress( + OodleLZ_Compressor compressor, + [MarshalAs(UnmanagedType.LPArray)] + byte[] rawBuf, + long rawLen, + [MarshalAs(UnmanagedType.LPArray)] + byte[] compBuf, + OodleLZ_CompressionLevel level, + IntPtr pOptions, + IntPtr dictionaryBase, + IntPtr lrm, + IntPtr scratchMem, + long scratchSize); + + private static long OodleLZ_Compress(OodleLZ_Compressor compressor, byte[] rawBuf, long rawLen, byte[] compBuf, OodleLZ_CompressionLevel level) + => OodleLZ_Compress(compressor, rawBuf, rawLen, compBuf, level, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0); + + + /// = OodleLZ_Compressor_Invalid + /// = OodleLZ_CompressionLevel_Normal + [DllImport("oo2core_6_win64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr OodleLZ_CompressOptions_GetDefault( + OodleLZ_Compressor compressor, + OodleLZ_CompressionLevel lzLevel); + + private static IntPtr OodleLZ_CompressOptions_GetDefault() + => OodleLZ_CompressOptions_GetDefault(OodleLZ_Compressor.OodleLZ_Compressor_Invalid, OodleLZ_CompressionLevel.OodleLZ_CompressionLevel_Normal); + + + /// + /// + /// + /// + /// = OodleLZ_FuzzSafe_Yes + /// = OodleLZ_CheckCRC_No + /// = OodleLZ_Verbosity_None + /// = NULL + /// = 0 + /// = NULL + /// = NULL + /// = NULL + /// = 0 + /// = OodleLZ_Decode_Unthreaded + [DllImport("oo2core_6_win64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern long OodleLZ_Decompress( + [MarshalAs(UnmanagedType.LPArray)] + byte[] compBuf, + long compBufSize, + [MarshalAs(UnmanagedType.LPArray)] + byte[] rawBuf, + long rawLen, + OodleLZ_FuzzSafe fuzzSafe, + OodleLZ_CheckCRC checkCRC, + OodleLZ_Verbosity verbosity, + IntPtr decBufBase, + long decBufSize, + IntPtr fpCallback, + IntPtr callbackUserData, + IntPtr decoderMemory, + long decoderMemorySize, + OodleLZ_Decode_ThreadPhase threadPhase); + + private static long OodleLZ_Decompress(byte[] compBuf, long compBufSize, byte[] rawBuf, long rawLen) + => OodleLZ_Decompress(compBuf, compBufSize, rawBuf, rawLen, + OodleLZ_FuzzSafe.OodleLZ_FuzzSafe_Yes, OodleLZ_CheckCRC.OodleLZ_CheckCRC_No, OodleLZ_Verbosity.OodleLZ_Verbosity_None, + IntPtr.Zero, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, OodleLZ_Decode_ThreadPhase.OodleLZ_Decode_Unthreaded); + + + [DllImport("oo2core_6_win64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern long OodleLZ_GetCompressedBufferSizeNeeded( + long rawSize); + + + [DllImport("oo2core_6_win64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern long OodleLZ_GetDecodeBufferSize( + long rawSize, + [MarshalAs(UnmanagedType.Bool)] + bool corruptionPossible); + + + [StructLayout(LayoutKind.Sequential)] + private struct OodleLZ_CompressOptions + { + public uint verbosity; + public int minMatchLen; + [MarshalAs(UnmanagedType.Bool)] + public bool seekChunkReset; + public int seekChunkLen; + public OodleLZ_Profile profile; + public int dictionarySize; + public int spaceSpeedTradeoffBytes; + public int maxHuffmansPerChunk; + [MarshalAs(UnmanagedType.Bool)] + public bool sendQuantumCRCs; + public int maxLocalDictionarySize; + public int makeLongRangeMatcher; + public int matchTableSizeLog2; + } + + + private enum OodleLZ_CheckCRC : int + { + OodleLZ_CheckCRC_No = 0, + OodleLZ_CheckCRC_Yes = 1, + OodleLZ_CheckCRC_Force32 = 0x40000000 + } + + public enum OodleLZ_CompressionLevel : int + { + OodleLZ_CompressionLevel_None = 0, + OodleLZ_CompressionLevel_SuperFast = 1, + OodleLZ_CompressionLevel_VeryFast = 2, + OodleLZ_CompressionLevel_Fast = 3, + OodleLZ_CompressionLevel_Normal = 4, + + OodleLZ_CompressionLevel_Optimal1 = 5, + OodleLZ_CompressionLevel_Optimal2 = 6, + OodleLZ_CompressionLevel_Optimal3 = 7, + OodleLZ_CompressionLevel_Optimal4 = 8, + OodleLZ_CompressionLevel_Optimal5 = 9, + + OodleLZ_CompressionLevel_HyperFast1 = -1, + OodleLZ_CompressionLevel_HyperFast2 = -2, + OodleLZ_CompressionLevel_HyperFast3 = -3, + OodleLZ_CompressionLevel_HyperFast4 = -4, + + OodleLZ_CompressionLevel_HyperFast = OodleLZ_CompressionLevel_HyperFast1, + OodleLZ_CompressionLevel_Optimal = OodleLZ_CompressionLevel_Optimal2, + OodleLZ_CompressionLevel_Max = OodleLZ_CompressionLevel_Optimal5, + OodleLZ_CompressionLevel_Min = OodleLZ_CompressionLevel_HyperFast4, + + OodleLZ_CompressionLevel_Force32 = 0x40000000, + OodleLZ_CompressionLevel_Invalid = OodleLZ_CompressionLevel_Force32 + } + + public enum OodleLZ_Compressor : int + { + OodleLZ_Compressor_Invalid = -1, + OodleLZ_Compressor_None = 3, + + OodleLZ_Compressor_Kraken = 8, + OodleLZ_Compressor_Leviathan = 13, + OodleLZ_Compressor_Mermaid = 9, + OodleLZ_Compressor_Selkie = 11, + OodleLZ_Compressor_Hydra = 12, + + OodleLZ_Compressor_BitKnit = 10, + OodleLZ_Compressor_LZB16 = 4, + OodleLZ_Compressor_LZNA = 7, + OodleLZ_Compressor_LZH = 0, + OodleLZ_Compressor_LZHLW = 1, + OodleLZ_Compressor_LZNIB = 2, + OodleLZ_Compressor_LZBLW = 5, + OodleLZ_Compressor_LZA = 6, + + OodleLZ_Compressor_Count = 14, + OodleLZ_Compressor_Force32 = 0x40000000 + } + + private enum OodleLZ_Decode_ThreadPhase : int + { + OodleLZ_Decode_ThreadPhase1 = 1, + OodleLZ_Decode_ThreadPhase2 = 2, + OodleLZ_Decode_ThreadPhaseAll = 3, + OodleLZ_Decode_Unthreaded = OodleLZ_Decode_ThreadPhaseAll + } + + private enum OodleLZ_FuzzSafe : int + { + OodleLZ_FuzzSafe_No = 0, + OodleLZ_FuzzSafe_Yes = 1 + } + + private enum OodleLZ_Profile : int + { + OodleLZ_Profile_Main = 0, + OodleLZ_Profile_Reduced = 1, + OodleLZ_Profile_Force32 = 0x40000000 + } + + private enum OodleLZ_Verbosity : int + { + OodleLZ_Verbosity_None = 0, + OodleLZ_Verbosity_Minimal = 1, + OodleLZ_Verbosity_Some = 2, + OodleLZ_Verbosity_Lots = 3, + OodleLZ_Verbosity_Force32 = 0x40000000 + } + } +} diff --git a/Switch_Toolbox_Library/Compression/STLibraryCompression.cs b/Switch_Toolbox_Library/Compression/STLibraryCompression.cs index 26b94a78..75fe38b3 100644 --- a/Switch_Toolbox_Library/Compression/STLibraryCompression.cs +++ b/Switch_Toolbox_Library/Compression/STLibraryCompression.cs @@ -712,6 +712,18 @@ namespace Toolbox.Library.IO return LZ4.LZ4Codec.Encode(data, inputOffset, data.Length); } } - } + public class Type_Oodle + { + public static byte[] Decompress(byte[] data, int decompressedSize) + { + return Toolbox.Library.Compression.Oodle.Decompress(data, decompressedSize); + } + + public static byte[] Compress(byte[] source, Compression.Oodle.OodleLZ_Compressor compressor, Compression.Oodle.OodleLZ_CompressionLevel level) + { + return Toolbox.Library.Compression.Oodle.Compress(source, compressor, level); + } + } + } } diff --git a/Switch_Toolbox_Library/Toolbox_Library.csproj b/Switch_Toolbox_Library/Toolbox_Library.csproj index 9977a353..6f67437e 100644 --- a/Switch_Toolbox_Library/Toolbox_Library.csproj +++ b/Switch_Toolbox_Library/Toolbox_Library.csproj @@ -248,6 +248,7 @@ +