diff --git a/.vs/Toolbox/v15/.suo b/.vs/Toolbox/v15/.suo index 19a6de11..425ccb18 100644 Binary files a/.vs/Toolbox/v15/.suo and b/.vs/Toolbox/v15/.suo differ diff --git a/File_Format_Library/FileFormats/Archives/HyruleWarriors/HWBinGzResource.cs b/File_Format_Library/FileFormats/Archives/HyruleWarriors/HWBinGzResource.cs new file mode 100644 index 00000000..ad65826c --- /dev/null +++ b/File_Format_Library/FileFormats/Archives/HyruleWarriors/HWBinGzResource.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Drawing; +using System.Threading.Tasks; +using Toolbox; +using System.Windows.Forms; +using Toolbox.Library; +using Toolbox.Library.IO; + +namespace FirstPlugin +{ + public class BinGzArchive : IArchiveFile, IFileFormat + { + public FileType FileType { get; set; } = FileType.Archive; + + public bool CanSave { get; set; } + public string[] Description { get; set; } = new string[] { "Hyrule Warriors Resource (bin.gz)" }; + public string[] Extension { get; set; } = new string[] { "*.pac" }; + public string FileName { get; set; } + public string FilePath { get; set; } + public IFileInfo IFileInfo { get; set; } + + public bool CanAddFiles { get; set; } + public bool CanRenameFiles { get; set; } + public bool CanReplaceFiles { get; set; } + public bool CanDeleteFiles { get; set; } + + public bool Identify(System.IO.Stream stream) + { + return (FileName.Contains(".bin.gz")); + } + + public Type[] Types + { + get + { + List types = new List(); + return types.ToArray(); + } + } + + public List files = new List(); + + public IEnumerable Files => files; + + public void ClearFiles() { files.Clear(); } + + private void CheckEndianness(FileReader reader) + { + + } + + private Stream CheckCompression(Stream stream) + { + using (var reader = new FileReader(stream, true)) + { + reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; + reader.SeekBegin(132); + ushort magic = reader.ReadUInt16(); + if (reader.ReadUInt16() == 0X78DA) + { + var data = STLibraryCompression.ZLIB.Decompress(reader.getSection(132, (int)reader.BaseStream.Length - 132)); + return new MemoryStream(data); + } + } + return stream; + } + + public void Load(Stream stream) + { + stream = CheckCompression(stream); + using (var reader = new FileReader(stream)) + { + CheckEndianness(reader); + + uint Count = reader.ReadUInt32(); + + uint[] Offsets = new uint[Count]; + uint[] Sizes = new uint[Count]; + + for (int i = 0; i < Count; i++) + { + Offsets[i] = reader.ReadUInt32(); + Sizes[i] = reader.ReadUInt32(); + } + + + for (int i = 0; i < Count; i++) + { + var fileEntry = new FileEntry(); + reader.SeekBegin(Offsets[i]); + string Magic = reader.ReadString(8); + switch (Magic) + { + case "G1TG0060": //PC or Wii U Texture + GITextureContainer GITextureU = new GITextureContainer(); + GITextureU.Read(reader, true); + break; + case "GT1G0600": //Switch Texture + GITextureContainer GITexture = new GITextureContainer(); + GITexture.Read(reader, false); + break; + } + + fileEntry.FileData = reader.ReadBytes((int)Sizes[i]); + fileEntry.FileName = $"File {i}"; + files.Add(fileEntry); + + + } + } + } + + public class GITextureContainer + { + public void Read(FileReader reader, bool IsWiiU) + { + long StartPos = reader.Position; + + uint FileSize = reader.ReadUInt32(); + uint DataOffset = reader.ReadUInt32(); + uint TextureCount = reader.ReadUInt32(); + uint unk = reader.ReadUInt32(); + uint unk2 = reader.ReadUInt32(); + uint[] unk3s = reader.ReadUInt32s((int)TextureCount); + + for (int i = 0; i < TextureCount; i++) + { + reader.SeekBegin(StartPos + DataOffset + (i * 4)); + + uint InfoOffset = reader.ReadUInt32(); + + reader.SeekBegin(DataOffset + InfoOffset); + byte unk4 = reader.ReadByte(); + byte format = reader.ReadByte(); + + } + } + } + + public class GITexture : STGenericTexture + { + public override bool CanEdit { get; set; } = false; + + public byte[] ImageData; + + public override TEX_FORMAT[] SupportedFormats + { + get + { + return new TEX_FORMAT[] { + TEX_FORMAT.R8G8B8A8_UNORM, + }; + } + } + + public override void SetImageData(Bitmap bitmap, int ArrayLevel) + { + } + + public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0) + { + return ImageData; + } + } + + public void Unload() + { + + } + + public byte[] Save() + { + return null; + } + + public bool AddFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + + public bool DeleteFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + + public class FileEntry : ArchiveFileInfo + { + + } + } +} diff --git a/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs b/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs index cfa444ac..6b780b2b 100644 --- a/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs +++ b/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs @@ -59,6 +59,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon TreeNode textureFolder = new TreeNode("Textures"); TreeNode modelFolder = new TreeNode("Models"); + TreeNode materialNamesFolder = new TreeNode("Material Names"); TreeNode chunkFolder = new TreeNode("Chunks"); public byte[] GetFile003Data() @@ -211,10 +212,19 @@ namespace FirstPlugin.LuigisMansion.DarkMoon case SubDataType.ModelTransform: using (var transformReader = new FileReader(chunkEntry.FileData)) { - if (transformReader.BaseStream.Length == 0x40) - currentModel.Transform = transformReader.ReadMatrix4(); - else - currentModel.Transform = OpenTK.Matrix4.Identity; + //This is possibly very wrong + //The data isn't always per mesh, but sometimes is + if (transformReader.BaseStream.Length / 0x40 == currentModel.Meshes.Count) + { + for (int i = 0; i < currentModel.Meshes.Count; i++) + currentModel.Meshes[i].Transform = transformReader.ReadMatrix4(); + } + } + break; + case SubDataType.MaterialName: + using (var matReader = new FileReader(chunkEntry.FileData)) + { + materialNamesFolder.Nodes.Add(matReader.ReadZeroTerminatedString()); } break; default: @@ -232,6 +242,9 @@ namespace FirstPlugin.LuigisMansion.DarkMoon if (textureFolder.Nodes.Count > 0) Nodes.Add(textureFolder); + + if (materialNamesFolder.Nodes.Count > 0) + Nodes.Add(materialNamesFolder); } } diff --git a/File_Format_Library/FileFormats/Archives/LM2/LM2_Enums.cs b/File_Format_Library/FileFormats/Archives/LM2/LM2_Enums.cs index 52337eaf..7dfe6083 100644 --- a/File_Format_Library/FileFormats/Archives/LM2/LM2_Enums.cs +++ b/File_Format_Library/FileFormats/Archives/LM2/LM2_Enums.cs @@ -33,10 +33,14 @@ namespace FirstPlugin.LuigisMansion.DarkMoon ModelTransform = 0x1301B001, //Matrix4x4. 0x40 in size MeshBuffers = 0x1301B005, //vertex and index buffer MaterialName = 0x1201B333, - MeshIndexTable = 0x12017105, + MeshIndexTable = 0x1201B007, MessageData = 0x12027020, ShaderData = 0x1401B400, TextureHeader = 0x0201B501, TextureData = 0x1701B502, + UILayoutMagic = 0x92027000, + UILayoutHeader = 0x12027001, + UILayoutData = 0x12027002, //Without header + UILayout = 0x02027003, //All parts combined } } diff --git a/File_Format_Library/FileFormats/Archives/LM2/LM2_Model.cs b/File_Format_Library/FileFormats/Archives/LM2/LM2_Model.cs index 296bc01e..1167de09 100644 --- a/File_Format_Library/FileFormats/Archives/LM2/LM2_Model.cs +++ b/File_Format_Library/FileFormats/Archives/LM2/LM2_Model.cs @@ -18,7 +18,6 @@ namespace FirstPlugin.LuigisMansion.DarkMoon public LM2_ModelInfo ModelInfo; public List Meshes = new List(); public List VertexBufferPointers = new List(); - public Matrix4 Transform { get; set; } public uint BufferStart; public uint BufferSize; @@ -86,6 +85,13 @@ namespace FirstPlugin.LuigisMansion.DarkMoon STGenericPolygonGroup polyGroup = new STGenericPolygonGroup(); genericObj.PolygonGroups.Add(polyGroup); + using (reader.TemporarySeek(BufferStart + VertexBufferPointers[i], System.IO.SeekOrigin.Begin)) + { + var bufferNodeDebug = new DebugVisualBytes(reader.ReadBytes((int)80 * mesh.VertexCount)); + bufferNodeDebug.Text = $"Buffer {mesh.DataFormat.ToString("x")}"; + genericObj.Nodes.Add(bufferNodeDebug); + } + if (!LM2_Mesh.FormatInfos.ContainsKey(mesh.DataFormat)) { Console.WriteLine($"Unsupported data format! " + mesh.DataFormat.ToString("x")); @@ -102,7 +108,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon case IndexFormat.Index_8: for (int f = 0; f < mesh.IndexCount; f++) polyGroup.faces.Add(reader.ReadByte()); - break; + break; case IndexFormat.Index_16: for (int f = 0; f < mesh.IndexCount; f++) polyGroup.faces.Add(reader.ReadUInt16()); @@ -112,14 +118,6 @@ namespace FirstPlugin.LuigisMansion.DarkMoon Console.WriteLine($"Mesh {genericObj.Text} Format {formatInfo.Format} BufferLength {formatInfo.BufferLength}"); uint bufferOffet = BufferStart + VertexBufferPointers[i]; - - using (reader.TemporarySeek(bufferOffet, System.IO.SeekOrigin.Begin)) - { - var bufferNodeDebug = new DebugVisualBytes(reader.ReadBytes((int)formatInfo.BufferLength * mesh.VertexCount)); - bufferNodeDebug.Text = "Buffer"; - genericObj.Nodes.Add(bufferNodeDebug); - } - /* for (int v = 0; v < mesh.VertexCount; v++) { reader.SeekBegin(bufferOffet + (v * formatInfo.BufferLength)); @@ -140,16 +138,22 @@ namespace FirstPlugin.LuigisMansion.DarkMoon UShortToFloatDecode(reader.ReadInt16()), UShortToFloatDecode(reader.ReadInt16())); - Console.WriteLine("F16 unk 1 " + reader.ReadUInt16()); - Console.WriteLine("F16 unk 2 " + reader.ReadUInt16()); + // reader.BaseStream.Position += 0x4; - // reader.BaseStream.Position += 0x4; - - vert.pos = Vector3.TransformPosition(vert.pos, Transform); + vert.pos = Vector3.TransformPosition(vert.pos, mesh.Transform); vert.uv0 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); + vert.nrm = new Vector3( + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16())); + reader.SeekBegin(bufferOffet + (v * formatInfo.BufferLength) + 38); + vert.col = new Vector4( + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16())); - Console.WriteLine("vert.uv0 " + vert.uv0); if (formatInfo.BufferLength == 22) { @@ -160,24 +164,24 @@ namespace FirstPlugin.LuigisMansion.DarkMoon } - // reader.BaseStream.Position += 0x2; + // reader.BaseStream.Position += 0x2; - /* vert.col = new Vector4( - UShortToFloatDecode(reader.ReadInt16()), - UShortToFloatDecode(reader.ReadInt16()), - UShortToFloatDecode(reader.ReadInt16()), - UShortToFloatDecode(reader.ReadInt16()));*/ + /* vert.col = new Vector4( + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()));*/ - /* reader.BaseStream.Position += 8; + /* reader.BaseStream.Position += 8; - // vert.uv1 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); - // vert.uv2 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); + // vert.uv1 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); + // vert.uv2 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); - vert.nrm = new Vector3( - UShortToFloatDecode(reader.ReadInt16()), - UShortToFloatDecode(reader.ReadInt16()), - UShortToFloatDecode(reader.ReadInt16()));*/ - } + vert.nrm = new Vector3( + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()), + UShortToFloatDecode(reader.ReadInt16()));*/ + } break; case VertexDataFormat.Float32: for (int v = 0; v < mesh.VertexCount; v++) @@ -188,7 +192,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon genericObj.vertices.Add(vert); vert.pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - vert.pos = Vector3.TransformPosition(vert.pos, Transform); + vert.pos = Vector3.TransformPosition(vert.pos, mesh.Transform); } break; case VertexDataFormat.Float32_32: @@ -199,7 +203,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon genericObj.vertices.Add(vert); vert.pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - vert.pos = Vector3.TransformPosition(vert.pos, Transform); + vert.pos = Vector3.TransformPosition(vert.pos, mesh.Transform); reader.BaseStream.Position += formatInfo.BufferLength - 0x14; } @@ -213,7 +217,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon genericObj.vertices.Add(vert); vert.pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); - vert.pos = Vector3.TransformPosition(vert.pos, Transform); + vert.pos = Vector3.TransformPosition(vert.pos, mesh.Transform); Console.WriteLine("F32_32 unk 1 " + reader.ReadUInt16()); Console.WriteLine("F32_32 unk 2 " + reader.ReadUInt16()); vert.uv0 = NormalizeUvCoordsToFloat(reader.ReadUInt16(), reader.ReadUInt16()); @@ -228,16 +232,6 @@ namespace FirstPlugin.LuigisMansion.DarkMoon } } - private static Vector4 Set_10_10_10_2_UNorm(uint value) - { - return new Vector4( - (value & 0b00000000_00000000_00000011_11111111) / 1023f, - ((value & 0b00000000_00001111_11111100_00000000) >> 10) / 1023f, - ((value & 0b00111111_11110000_00000000_00000000) >> 20) / 1023f, - ((value & 0b11000000_00000000_00000000_00000000) >> 30) / 3f); - } - - public static Vector2 NormalizeUvCoordsToFloat(ushort U, ushort V) { return new Vector2( U / 1024f, V / 1024f); @@ -354,6 +348,8 @@ namespace FirstPlugin.LuigisMansion.DarkMoon public ushort Unknown7 { get; private set; } public uint HashID { get; private set; } + public Matrix4 Transform { get; set; } = Matrix4.Identity; + public void Read(FileReader reader) { IndexStartOffset = reader.ReadUInt32(); diff --git a/File_Format_Library/FileFormats/Rom/NSP.cs b/File_Format_Library/FileFormats/Rom/NSP.cs index fbcba09c..babf0f78 100644 --- a/File_Format_Library/FileFormats/Rom/NSP.cs +++ b/File_Format_Library/FileFormats/Rom/NSP.cs @@ -130,6 +130,21 @@ namespace FirstPlugin } } + public override void Export() + { + string fileName = Path.GetFileName(FileName.RemoveIllegaleFolderNameCharacters()); + + SaveFileDialog sfd = new SaveFileDialog(); + sfd.FileName = fileName; + sfd.DefaultExt = Path.GetExtension(fileName); + sfd.Filter = "Raw Data (*.*)|*.*"; + + if (sfd.ShowDialog() == DialogResult.OK) + { + ParentROMFS.OpenFile(File).WriteAllBytes($"{sfd.FileName}"); + } + } + public FileEntry(Romfs romfs, RomfsFile romfsFile) { ParentROMFS = romfs; diff --git a/File_Format_Library/FileFormats/Rom/RomfsNodeWrapper.cs b/File_Format_Library/FileFormats/Rom/RomfsNodeWrapper.cs index 0a4b49c1..c091fc58 100644 --- a/File_Format_Library/FileFormats/Rom/RomfsNodeWrapper.cs +++ b/File_Format_Library/FileFormats/Rom/RomfsNodeWrapper.cs @@ -86,6 +86,7 @@ namespace FirstPlugin editor.LoadData(mem.ToArray()); } } + public override void OnDoubleMouseClick(TreeView treeview) { string filePath = GetFilePath(); diff --git a/File_Format_Library/Main.cs b/File_Format_Library/Main.cs index 18da58b2..bca27636 100644 --- a/File_Format_Library/Main.cs +++ b/File_Format_Library/Main.cs @@ -357,6 +357,7 @@ namespace FirstPlugin Formats.Add(typeof(TPL)); Formats.Add(typeof(BFTTF)); Formats.Add(typeof(PACx30XL)); + Formats.Add(typeof(BinGzArchive)); // Formats.Add(typeof(GFA)); diff --git a/Switch_Toolbox_Library/Generics/GenericTexture.cs b/Switch_Toolbox_Library/Generics/GenericTexture.cs index a50ae8fd..cfd4afa5 100644 --- a/Switch_Toolbox_Library/Generics/GenericTexture.cs +++ b/Switch_Toolbox_Library/Generics/GenericTexture.cs @@ -930,28 +930,23 @@ namespace Toolbox.Library public static int GenerateTotalMipCount(uint Width, uint Height) { - int MipmapNum = 0; - uint num = Math.Max(Width, Height); + int mipCount = 1; int width = (int)Width; int height = (int)Height; - while (true) + while (width > 1 || height > 1) { - num >>= 1; + ++mipCount; - width = width / 2; - height = height / 2; - if (width <= 0 || height <= 0) - break; - - if (num > 0) - ++MipmapNum; - else - break; + if (width > 1) + width /= 2; + + if (height > 1) + height /= 2; } - return MipmapNum; + return mipCount; } public static string SetNameFromPath(string path)