diff --git a/BrawlboxHelper/app.config b/BrawlboxHelper/app.config index f6e7dca8..996f4bcc 100644 --- a/BrawlboxHelper/app.config +++ b/BrawlboxHelper/app.config @@ -6,6 +6,10 @@ + + + + \ No newline at end of file diff --git a/File_Format_Library/FileFormats/BFRES/BFRES.cs b/File_Format_Library/FileFormats/BFRES/BFRES.cs index 19e21f60..b200e416 100644 --- a/File_Format_Library/FileFormats/BFRES/BFRES.cs +++ b/File_Format_Library/FileFormats/BFRES/BFRES.cs @@ -802,6 +802,9 @@ namespace FirstPlugin BFRESRender.ModelTransform = MarioCostumeEditor.SetTransform(FileName); BFRESRender.ResFileNode = this; + if (this.FileName.Contains("bfres.mc")) + MeshCodec.Prepare(); + if (IsWiiU) { LoadFile(new Syroot.NintenTools.Bfres.ResFile(stream)); @@ -835,6 +838,7 @@ namespace FirstPlugin } } } + public void Unload() { BFRESRender.Destroy(); diff --git a/File_Format_Library/FileFormats/BFRES/BfresSwitch.cs b/File_Format_Library/FileFormats/BFRES/BfresSwitch.cs index 1f07e891..75f20c25 100644 --- a/File_Format_Library/FileFormats/BFRES/BfresSwitch.cs +++ b/File_Format_Library/FileFormats/BFRES/BfresSwitch.cs @@ -266,7 +266,9 @@ namespace FirstPlugin Syroot.Maths.Vector4F[] vec4t0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4b0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4w0 = new Syroot.Maths.Vector4F[0]; + Syroot.Maths.Vector4F[] vec4w1 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4i0 = new Syroot.Maths.Vector4F[0]; + Syroot.Maths.Vector4F[] vec4i1 = new Syroot.Maths.Vector4F[0]; //For shape morphing Syroot.Maths.Vector4F[] vec4Positions1 = new Syroot.Maths.Vector4F[0]; @@ -298,6 +300,10 @@ namespace FirstPlugin vec4w0 = AttributeData(att, helper, "_w0"); if (att.Name == "_i0") vec4i0 = AttributeData(att, helper, "_i0"); + if (att.Name == "_w1") + vec4w1 = AttributeData(att, helper, "_w1"); + if (att.Name == "_i1") + vec4i1 = AttributeData(att, helper, "_i1"); if (att.Name == "_p1") vec4Positions1 = AttributeData(att, helper, "_p1"); @@ -335,6 +341,17 @@ namespace FirstPlugin if (fshp.VertexSkinCount > 3) v.boneWeights.Add(vec4w0[i].W); } + if (vec4w1.Length > 0) + { + if (fshp.VertexSkinCount > 4) + v.boneWeights.Add(vec4w1[i].X); + if (fshp.VertexSkinCount > 5) + v.boneWeights.Add(vec4w1[i].Y); + if (fshp.VertexSkinCount > 6) + v.boneWeights.Add(vec4w1[i].Z); + if (fshp.VertexSkinCount > 7) + v.boneWeights.Add(vec4w1[i].W); + } if (vec4i0.Length > 0) { if (fshp.VertexSkinCount > 0) @@ -346,7 +363,17 @@ namespace FirstPlugin if (fshp.VertexSkinCount > 3) v.boneIds.Add((int)vec4i0[i].W); } - + if (vec4i1.Length > 0) + { + if (fshp.VertexSkinCount > 4) + v.boneIds.Add((int)vec4i1[i].X); + if (fshp.VertexSkinCount > 5) + v.boneIds.Add((int)vec4i1[i].Y); + if (fshp.VertexSkinCount > 6) + v.boneIds.Add((int)vec4i1[i].Z); + if (fshp.VertexSkinCount > 7) + v.boneIds.Add((int)vec4i1[i].W); + } if (vec4t0.Length > 0) v.tan = new Vector4(vec4t0[i].X, vec4t0[i].Y, vec4t0[i].Z, vec4t0[i].W); if (vec4b0.Length > 0) diff --git a/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs b/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs new file mode 100644 index 00000000..48f0914c --- /dev/null +++ b/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Syroot.NintenTools.NSW.Bfres; +using Toolbox.Library; +using ZstdSharp.Unsafe; + +namespace FirstPlugin +{ + internal class MeshCodec + { + static ResFile ExternalStringBinary; + + public static void Prepare() + { + //Check if a valid directory exists + string path = Path.Combine(Runtime.TotkGamePath, "Shader", "ExternalBinaryString.bfres.mc"); + if (!File.Exists(path)) + { + MessageBox.Show("A game dump of TOTK is required to load this file. Please select the romfs folder path."); + + FolderSelectDialog dlg = new FolderSelectDialog(); + if (dlg.ShowDialog() == DialogResult.OK) + { + Runtime.TotkGamePath = dlg.SelectedPath; + path = Path.Combine(Runtime.TotkGamePath, "Shader", "ExternalBinaryString.bfres.mc"); + Toolbox.Library.Config.Save(); + } + } + + if (!File.Exists(path)) + { + MessageBox.Show($"Given folder was not valid! Expecting file {path}"); + return; + } + + LoadExternalStrings(); + } + + static void LoadExternalStrings() + { + if (ExternalStringBinary != null) + return; + + string path = Path.Combine(Runtime.TotkGamePath, "Shader", "ExternalBinaryString.bfres.mc"); + byte[] data = DecompressMeshCodec(path); + //Load string table into memory + //Strings are stored in a static list which will be used for opened bfres + ExternalStringBinary = new ResFile(new MemoryStream(data)); + } + + static byte[] DecompressMeshCodec(string file) + { + using (var fs = File.OpenRead(file)) + using (var reader = new BinaryReader(fs)) + { + reader.ReadUInt32(); //Magic + reader.ReadUInt32(); //Version 1.1.0.0 + var flags = reader.ReadInt32(); + var decompressed_size = (flags >> 5) << (flags & 0xf); + + reader.BaseStream.Seek(0xC, SeekOrigin.Begin); + byte[] src = reader.ReadBytes((int)reader.BaseStream.Length - 0xC); + return Decompress(src, (uint)decompressed_size); + } + } + + static unsafe byte[] Decompress(byte[] src, uint decompressed_size) + { + var dctx = Methods.ZSTD_createDCtx(); + Methods.ZSTD_DCtx_setFormat(dctx, ZSTD_format_e.ZSTD_f_zstd1_magicless); + var uncompressed = new byte[decompressed_size]; + fixed (byte* srcPtr = src) + fixed (byte* uncompressedPtr = uncompressed) + { + var decompressedLength = Methods.ZSTD_decompressDCtx(dctx, uncompressedPtr, (uint)uncompressed.Length, srcPtr, (uint)src.Length); + + byte[] arr = new byte[(uint)decompressed_size]; + Marshal.Copy((IntPtr)uncompressedPtr, arr, 0, arr.Length); + return arr; + } + } + } +} diff --git a/Switch_Toolbox_Library/Compression/Formats/Zstb.cs b/Switch_Toolbox_Library/Compression/Formats/Zstb.cs index 74c8a477..069d0dbb 100644 --- a/Switch_Toolbox_Library/Compression/Formats/Zstb.cs +++ b/Switch_Toolbox_Library/Compression/Formats/Zstb.cs @@ -82,7 +82,26 @@ namespace Toolbox.Library { byte[] dictionary = new byte[0]; - string folder = Path.Combine(Runtime.ExecutableDir, "Lib", "ZstdDictionaries"); + var userDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SwitchToolbox"); + if (!Directory.Exists(userDir)) + Directory.CreateDirectory(userDir); + + string folder = Path.Combine(userDir, "TOTK", "ZstdDictionaries"); + + //Check if old directory exists and move it + string folderOld = Path.Combine(Runtime.ExecutableDir, "Lib", "ZstdDictionaries"); + if (Directory.Exists(folderOld)) + { + //Create folder for TOTK contents if it does not exist + if (!Directory.Exists(Path.Combine(userDir, "TOTK"))) + Directory.CreateDirectory(Path.Combine(userDir, "TOTK")); + //Remove previous folder with any old files incase it gets updated with additional content + if (Directory.Exists(folder)) + Directory.Delete(folder, true); + //Move old to new directory + Directory.Move(folderOld, folder); + } + if (Directory.Exists(folder)) { void CheckZDic(string fileName, string expectedExtension) diff --git a/Switch_Toolbox_Library/Config.cs b/Switch_Toolbox_Library/Config.cs index 873ecd70..63e6da8b 100644 --- a/Switch_Toolbox_Library/Config.cs +++ b/Switch_Toolbox_Library/Config.cs @@ -181,6 +181,9 @@ namespace Toolbox.Library case "BotwGamePath": Runtime.BotwGamePath = node.InnerText; break; + case "TotkGamePath": + Runtime.TotkGamePath = node.InnerText; + break; case "SpecularCubeMapPath": Runtime.PBR.SpecularCubeMapPath = node.InnerText; break; @@ -511,6 +514,7 @@ namespace Toolbox.Library PathsNode.AppendChild(createNode(doc, "Mk8dGamePath", Runtime.Mk8dGamePath.ToString())); PathsNode.AppendChild(createNode(doc, "TpGamePath", Runtime.TpGamePath.ToString())); PathsNode.AppendChild(createNode(doc, "BotwGamePath", Runtime.BotwGamePath.ToString())); + PathsNode.AppendChild(createNode(doc, "TotkGamePath", Runtime.TotkGamePath.ToString())); PathsNode.AppendChild(createNode(doc, "SpecularCubeMapPath", Runtime.PBR.SpecularCubeMapPath.ToString())); PathsNode.AppendChild(createNode(doc, "DiffuseCubeMapPath", Runtime.PBR.DiffuseCubeMapPath.ToString())); PathsNode.AppendChild(createNode(doc, "PkSwShGamePath", Runtime.PkSwShGamePath.ToString())); diff --git a/Switch_Toolbox_Library/Runtime.cs b/Switch_Toolbox_Library/Runtime.cs index 03edf497..f6eda5b5 100644 --- a/Switch_Toolbox_Library/Runtime.cs +++ b/Switch_Toolbox_Library/Runtime.cs @@ -39,6 +39,7 @@ namespace Toolbox.Library public static string SmoGamePath = ""; public static string TpGamePath = ""; public static string BotwGamePath = ""; + public static string TotkGamePath = ""; public static bool ShowCloseDialog = true; diff --git a/Switch_Toolbox_Library/Toolbox_Library.csproj b/Switch_Toolbox_Library/Toolbox_Library.csproj index 93c4a470..11825169 100644 --- a/Switch_Toolbox_Library/Toolbox_Library.csproj +++ b/Switch_Toolbox_Library/Toolbox_Library.csproj @@ -162,8 +162,8 @@ - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll diff --git a/Switch_Toolbox_Library/app.config b/Switch_Toolbox_Library/app.config index 32c837a6..ccfe1f06 100644 --- a/Switch_Toolbox_Library/app.config +++ b/Switch_Toolbox_Library/app.config @@ -1,24 +1,28 @@ - + - + - - + + - - + + - - + + - - + + + + + + - + diff --git a/Switch_Toolbox_Library/packages.config b/Switch_Toolbox_Library/packages.config index 36dd0209..b4f74633 100644 --- a/Switch_Toolbox_Library/packages.config +++ b/Switch_Toolbox_Library/packages.config @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/Toolbox/App.config b/Toolbox/App.config index 6e97d895..5e55850d 100644 --- a/Toolbox/App.config +++ b/Toolbox/App.config @@ -1,27 +1,27 @@ - + - + - - + + - - + + - - + + - - + + - + diff --git a/Toolbox/System.Runtime.CompilerServices.Unsafe.dll b/Toolbox/System.Runtime.CompilerServices.Unsafe.dll deleted file mode 100644 index 63403d72..00000000 Binary files a/Toolbox/System.Runtime.CompilerServices.Unsafe.dll and /dev/null differ diff --git a/Toolbox/Toolbox.csproj b/Toolbox/Toolbox.csproj index 505ee49e..aa60a46c 100644 --- a/Toolbox/Toolbox.csproj +++ b/Toolbox/Toolbox.csproj @@ -692,9 +692,6 @@ PreserveNewest - - PreserveNewest -