diff --git a/.vs/Toolbox/v15/.suo b/.vs/Toolbox/v15/.suo index b4a89afb..4a5cabcb 100644 Binary files a/.vs/Toolbox/v15/.suo and b/.vs/Toolbox/v15/.suo differ diff --git a/File_Format_Library/FileFormats/Archives/LM2/LM2_ChunkTable.cs b/File_Format_Library/FileFormats/Archives/LM2/LM2_ChunkTable.cs new file mode 100644 index 00000000..59424b6c --- /dev/null +++ b/File_Format_Library/FileFormats/Archives/LM2/LM2_ChunkTable.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.IO; + +namespace FirstPlugin +{ + //Table consists of 2 chunk entry lists that define how the .data reads sections + public class LM2_ChunkTable + { + private const int ChunkInfoIdenfier = 0x2001301; + + //I am uncertain how these chunk lists work. There is first a list with an identifier and one extra unknown + //The second list can contain the same entries as the other list, however it may include more chunks + //Example, the first list may have image headers, while the second include both image headers and image blocks + public List ChunkEntries = new List(); + public List ChunkSubEntries = new List(); + + public class ChunkEntry + { + public uint Unknown1; + public uint ChunkOffset; + public uint ChunkType; + public uint Unknown2; + public uint Unknown3; + } + + public class ChunkSubEntry + { + public uint ChunkOffset; + public uint ChunkType; + public uint Unknown; + } + + public void Read(FileReader tableReader) + { + //Each data type has chunk info. There is no counter so keep checking idenfier + while (tableReader.ReadUInt32() == ChunkInfoIdenfier) + { + ChunkEntry entry = new ChunkEntry(); + ChunkEntries.Add(entry); + + entry.Unknown1 = tableReader.ReadUInt32(); //8 + entry.ChunkOffset = tableReader.ReadUInt32(); //The chunk offset in the file. Relative to the first chunk position in the file + entry.ChunkType = tableReader.ReadUInt32(); //The type of chunk. 0x8701B5 for example for texture info + entry.Unknown2 = tableReader.ReadUInt32(); + + //This increases by 2 each chunk info, however the starting value is not 0 + //Note the last entry does not have this + entry.Unknown3 = tableReader.ReadUInt32(); + } + + if (ChunkEntries.Count > 0) + ChunkEntries.LastOrDefault().Unknown3 = 0; + + tableReader.Seek(-4); //Seek 4 back as the last entry lacks unkown 4 + //Check the chunk types + //This time it includes more chunks (like image blocks) + + //Read to the end of the file as the rest of the table are types, offsets, and an unknown value + while (!tableReader.EndOfStream && tableReader.Position <= tableReader.BaseStream.Length - 12) + { + ChunkSubEntry subEntry = new ChunkSubEntry(); + subEntry.ChunkType = tableReader.ReadUInt32(); //The type of chunk. 0x8701B5 for example for texture info + subEntry.Unknown = tableReader.ReadUInt32(); //This seems to be the same value as the other Unknown2 in the last section + subEntry.ChunkOffset = tableReader.ReadUInt32(); //The chunk offset in the file. Relative to the first chunk position in the file + ChunkSubEntries.Add(subEntry); + } + } + } +} diff --git a/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs b/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs index 9dddf552..c62f23fc 100644 --- a/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs +++ b/File_Format_Library/FileFormats/Archives/LM2/LM2_DICT.cs @@ -13,7 +13,7 @@ using System.Drawing; namespace FirstPlugin { //Parse info based on https://github.com/TheFearsomeDzeraora/LM2L - public class LM2_DICT : TreeNodeFile, IFileFormat + public class LM2_DICT : TreeNodeFile, IFileFormat, IArchiveFile { public FileType FileType { get; set; } = FileType.Archive; @@ -48,9 +48,14 @@ namespace FirstPlugin } public List files = new List(); + public IEnumerable Files => files; + + public void ClearFiles() { files.Clear(); } public bool IsCompressed = false; + public LM2_ChunkTable ChunkTable; + public void Load(System.IO.Stream stream) { using (var reader = new FileReader(stream)) @@ -65,15 +70,46 @@ namespace FirstPlugin reader.SeekBegin(0x2C); byte[] Unknowns = reader.ReadBytes((int)FileCount); + + long FileTablePos = reader.Position; for (int i = 0; i < FileCount; i++) { var file = new FileEntry(this); file.Read(reader); - if (file.FileType != 0) + + //Skip the file table entries as those are not needed to be loaded + if (file.FileType != 0 && i > 1) { - file.Text = $"File {i} (Unknowns {file.FileType} {file.Unknown2} {file.Unknown3})"; + file.FileName = $"File {i} (FileType: ({file.FileType}) Unknowns: {file.Unknown2} {file.Unknown3})"; files.Add(file); } + //The first file stores a chunk layout + //The second one seems to be a duplicate? + if (i == 0) + { + using (var tableReader = new FileReader(file.FileData)) + { + ChunkTable = new LM2_ChunkTable(); + ChunkTable.Read(tableReader); + + TreeNode debugFolder = new TreeNode("DEBUG TABLE INFO"); + Nodes.Add(debugFolder); + + TreeNode list1 = new TreeNode("Entry List 1"); + TreeNode list2 = new TreeNode("Entry List 2 "); + debugFolder.Nodes.Add(list1); + debugFolder.Nodes.Add(list2); + + foreach (var chunk in ChunkTable.ChunkEntries) + { + list1.Nodes.Add($"ChunkOffset {chunk.ChunkOffset} ChunkType {chunk.ChunkType.ToString("X")} Unknown1 {chunk.Unknown1} Unknown2 {chunk.Unknown2} Unknown3 {chunk.Unknown3}"); + } + foreach (var chunk in ChunkTable.ChunkSubEntries) + { + list2.Nodes.Add($"ChunkOffset {chunk.ChunkOffset} ChunkType {chunk.ChunkType.ToString("X")} Unknown {chunk.Unknown}"); + } + } + } } //Now go through each file and format and connect the headers and blocks @@ -85,13 +121,14 @@ namespace FirstPlugin for (int i = 0; i < files.Count; i++) { - if (files[i].FileType == FileEntry.FileDataType.Texture) + if (files[i].FileType == FileEntry.DataType.Texture) { if (files[i].Unknown3 == 1) //Info { //Read the info using (var textureReader = new FileReader(files[i].FileData)) { + int headerIndex = 0; while (textureReader.ReadUInt32() == TexturePOWE.Identifier) { var texture = new TexturePOWE(); @@ -99,7 +136,7 @@ namespace FirstPlugin texture.SelectedImageKey = texture.ImageKey; texture.Index = ImageIndex; texture.Read(textureReader); - texture.Text = $"Texture {ImageIndex}"; + texture.Text = $"Texture {headerIndex++}"; textureFolder.Nodes.Add(texture); Textures.Add(texture); } @@ -120,8 +157,6 @@ namespace FirstPlugin ImageIndex++; } } - else - Nodes.Add(files[i]); } if (textureFolder.Nodes.Count > 0) @@ -231,23 +266,23 @@ namespace FirstPlugin } } - public class FileEntry : TreeNodeCustom + public class FileEntry : ArchiveFileInfo { public LM2_DICT ParentDictionary { get; set; } public uint Offset; public uint DecompressedSize; public uint CompressedSize; - public FileDataType FileType; + public DataType FileType; public byte Unknown2; public byte Unknown3; //Possibly the effect? 0 for image block, 1 for info - public enum FileDataType : ushort + public enum DataType : ushort { Texture = 0x80, } - public byte[] FileData + public override byte[] FileData { get { return GetData(); } set @@ -256,18 +291,6 @@ namespace FirstPlugin } } - public override void OnClick(TreeView treeview) - { - HexEditor editor = (HexEditor)LibraryGUI.GetActiveContent(typeof(HexEditor)); - if (editor == null) - { - editor = new HexEditor(); - LibraryGUI.LoadEditor(editor); - } - editor.Dock = DockStyle.Fill; - editor.LoadData(FileData); - } - public FileEntry(LM2_DICT dict) { ParentDictionary = dict; @@ -278,7 +301,7 @@ namespace FirstPlugin Offset = reader.ReadUInt32(); DecompressedSize = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); - FileType = reader.ReadEnum(false); + FileType = reader.ReadEnum(false); Unknown2 = reader.ReadByte(); Unknown3 = reader.ReadByte(); } diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs index 94cd6afe..564fd05d 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs @@ -1403,6 +1403,12 @@ namespace Bfres.Structs vert.Data = weights.ToArray(); vert.Format = att.Format; atrib.Add(vert); + + for (int i = 0; i < weights.Count; i++) + { + Console.WriteLine($"w {i} {weights[i]}"); + } + } if (att.Name == "_i0") { diff --git a/File_Format_Library/FileFormats/Custom/CsvModels.cs b/File_Format_Library/FileFormats/Custom/CsvModels.cs index 11673773..cc00733a 100644 --- a/File_Format_Library/FileFormats/Custom/CsvModels.cs +++ b/File_Format_Library/FileFormats/Custom/CsvModels.cs @@ -264,7 +264,7 @@ namespace FirstPlugin break; } - if (objects[0].weightsT.Count != objects[0].vertices.Count) + if (objects[0].weightsT.Count > 0 && objects[0].weightsT.Count != objects[0].vertices.Count) throw new Exception("Incorrect vertex amount"); foreach (STGenericObject obj in objects) @@ -277,16 +277,20 @@ namespace FirstPlugin foreach (float f in obj.weightsT[v]) obj.vertices[v].boneWeights.Add(f); } + + int vID = 0; foreach (Vertex v in obj.vertices) { if (v.boneNames.Count == 1) - Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]}"); + Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]}"); if (v.boneNames.Count == 2) - Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}"); + Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}"); if (v.boneNames.Count == 3) - Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}"); + Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}"); if (v.boneNames.Count == 4) - Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}"); + Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}"); + + vID++; } } diff --git a/File_Format_Library/File_Format_Library.csproj b/File_Format_Library/File_Format_Library.csproj index e5368f88..4d8be6a6 100644 --- a/File_Format_Library/File_Format_Library.csproj +++ b/File_Format_Library/File_Format_Library.csproj @@ -204,6 +204,7 @@ + diff --git a/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.dll b/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.dll index 3223c600..fc0988e9 100644 Binary files a/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.dll and b/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.dll differ diff --git a/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.pdb b/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.pdb index 96590861..eca9f4d5 100644 Binary files a/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.pdb and b/Toolbox/Lib/Syroot.NintenTools.NSW.Bfres.pdb differ