diff --git a/File_Format_Library/FileFormats/BCSV/BCSV.cs b/File_Format_Library/FileFormats/BCSV/BCSV.cs new file mode 100644 index 00000000..d1b662f0 --- /dev/null +++ b/File_Format_Library/FileFormats/BCSV/BCSV.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox; +using System.Windows.Forms; +using Toolbox.Library; +using Toolbox.Library.IO; +using Toolbox.Library.Forms; + +namespace FirstPlugin +{ + public class BCSV : IEditor, IFileFormat, IConvertableTextFormat + { + public FileType FileType { get; set; } = FileType.Parameter; + + public bool CanSave { get; set; } + public string[] Description { get; set; } = new string[] { "Binary CSV" }; + public string[] Extension { get; set; } = new string[] { "*.bcsv" }; + public string FileName { get; set; } + public string FilePath { get; set; } + public IFileInfo IFileInfo { get; set; } + + public bool Identify(System.IO.Stream stream) + { + using (var reader = new Toolbox.Library.IO.FileReader(stream, true)) + { + return reader.CheckSignature(4, "VSCB", 12); + } + } + + public Type[] Types + { + get + { + List types = new List(); + return types.ToArray(); + } + } + + public TextEditor OpenForm() + { + return new TextEditor(); + } + + public void FillEditor(UserControl control) + { + ((TextEditor)control).FileFormat = this; + ((TextEditor)control).FillEditor(ConvertToString()); + ((TextEditor)control).IsYAML = true; + + } + + public BCSVParse BCVFile; + + #region Text Converter Interface + public TextFileType TextFileType => TextFileType.Yaml; + public bool CanConvertBack => false; + + public string ConvertToString() + { + StringBuilder strBuilder = new StringBuilder(); + using (var textWriter = new System.IO.StringWriter(strBuilder)) + { + for (int i = 0; i < BCVFile.Entries.Count; i++) + { + textWriter.WriteLine($"Entry_{i}:"); + foreach (var field in BCVFile.Entries[i].Fields) { + textWriter.WriteLine($" {field.Key}: {field.Value}"); + } + } + } + return strBuilder.ToString(); + } + + public void ConvertFromString(string text) + { + } + + #endregion + + public void Load(System.IO.Stream stream) { + BCVFile = new BCSVParse(); + BCVFile.Read(new FileReader(stream)); + } + + public void Unload() + { + } + + public void Save(System.IO.Stream stream) { + BCVFile.Write(new FileWriter(stream)); + } + } +} diff --git a/File_Format_Library/FileFormats/BCSV/BCSVParse.cs b/File_Format_Library/FileFormats/BCSV/BCSVParse.cs new file mode 100644 index 00000000..6c639118 --- /dev/null +++ b/File_Format_Library/FileFormats/BCSV/BCSVParse.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.IO; + +namespace FirstPlugin +{ + public class BCSVParse + { + public class Field + { + public uint Hash { get; set; } + public uint Offset { get; set; } + + public object Value; + } + + public class DataEntry + { + public Dictionary Fields; + } + + public List Entries = new List(); + + public void Read(FileReader reader) + { + uint numEntries = reader.ReadUInt32(); + uint entrySize = reader.ReadUInt32(); + ushort numFields = reader.ReadUInt16(); + ushort version = reader.ReadUInt16(); + uint magic = reader.ReadUInt32(); + uint unk = reader.ReadUInt32(); //Always 100000 + reader.ReadUInt32();//0 + reader.ReadUInt32();//0 + + Field[] fields = new Field[numFields]; + for (int i = 0; i < numFields; i++) { + fields[i] = new Field() + { + Hash = reader.ReadUInt32(), + Offset = reader.ReadUInt32(), + }; + } + for (int i = 0; i < numEntries; i++) + { + DataEntry entry = new DataEntry(); + Entries.Add(entry); + entry.Fields = new Dictionary(); + + long pos = reader.Position; + for (int f = 0; f < fields.Length; f++) + { + DataType type = DataType.String; + uint size = entrySize - fields[f].Offset; + if (f < fields.Length - 1) { + size = fields[f + 1].Offset - fields[f].Offset; + } + if (size == 1) + type = DataType.Byte; + if (size == 2) + type = DataType.Uint16; + if (size == 4) + type = DataType.Uint32; + if (size == 32) + type = DataType.Uint32; + + + reader.SeekBegin(pos + fields[f].Offset); + object value = 0; + string name = fields[f].Hash.ToString("x"); + switch (type) + { + case DataType.Byte: + value = reader.ReadByte(); + break; + case DataType.Float: + value = reader.ReadSingle(); + break; + case DataType.Uint16: + value = reader.ReadUInt16(); + break; + case DataType.Uint32: + value = reader.ReadUInt32(); + break; + case DataType.String: + value = reader.ReadZeroTerminatedString(Encoding.UTF8); + break; + } + + entry.Fields.Add(name, value); + } + + reader.SeekBegin(pos + entrySize); + } + } + + public enum DataType + { + Byte, + Uint16, + Uint32, + Uint64, + Float, + String, + } + + public void Write(FileWriter writer) + { + + } + + + + private static Dictionary hashes = new Dictionary(); + public static Dictionary Hashes + { + get { + if (hashes.Count == 0) + CalculateHashes(); + return hashes; } + } + + public static void CalculateHashes() + { + if (hashes.Count > 0) + return; + + foreach (string hashStr in Properties.Resources.ACNH.Split('\n')) + { + string HashString = hashStr.TrimEnd(); + + uint hash = (uint)Toolbox.Library.Security.Cryptography.Crc32.Compute(HashString); + if (!hashes.ContainsKey(hash)) + hashes.Add(hash, HashString); + } + + foreach (var hash in AampLibraryCSharp.Hashes.hashName) + if (!hashes.ContainsKey(hash.Key)) + hashes.Add(hash.Key, hash.Value); + } + + static uint NameHash(string name) + { + uint result = 0; + for (int i = 0; i < name.Length; i++) + { + result = name[i] + result * 0x00000065; + } + return result; + } + + public static uint stringToHash(string name) + { + int hash = 0; + for (int i = 0; i < name.Length; i++) + { + hash *= 0x1F; + hash += name[i]; + } + + return (uint)hash; + } + } +} diff --git a/File_Format_Library/Main.cs b/File_Format_Library/Main.cs index 3411a541..6113deb1 100644 --- a/File_Format_Library/Main.cs +++ b/File_Format_Library/Main.cs @@ -92,6 +92,7 @@ namespace FirstPlugin public STToolStripItem[] TitleBarExtensions => null; readonly STToolStripItem[] toolsExt = new STToolStripItem[3]; + public MenuExt() { toolsExt[0] = new STToolStripItem("Super Mario Odyssey"); @@ -101,7 +102,6 @@ namespace FirstPlugin toolsExt[1] = new STToolStripItem("Mario Kart 8"); toolsExt[1].DropDownItems.Add(new STToolStripItem("Probe Light Converter", GenerateProbeLightBounds)); - toolsExt[2] = new STToolStripItem("Breath Of The Wild"); toolsExt[2].DropDownItems.Add(new STToolStripItem("Actor Editor", ActorEditor)); @@ -341,6 +341,7 @@ namespace FirstPlugin { List Formats = new List(); Formats.Add(typeof(BFRES)); + Formats.Add(typeof(BCSV)); Formats.Add(typeof(TVOL)); Formats.Add(typeof(BTI)); Formats.Add(typeof(TXE)); @@ -451,9 +452,9 @@ namespace FirstPlugin Formats.Add(typeof(WTA)); Formats.Add(typeof(BinGzArchive)); Formats.Add(typeof(BNR)); - // Formats.Add(typeof(MPBIN)); + // Formats.Add(typeof(MPBIN)); // Formats.Add(typeof(HSF)); - // Formats.Add(typeof(ATB)); + // Formats.Add(typeof(ATB)); // Formats.Add(typeof(LayoutBXLYT.BLO));