diff options
Diffstat (limited to '')
-rw-r--r-- | NW4RTools/BrresWriter.cs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/NW4RTools/BrresWriter.cs b/NW4RTools/BrresWriter.cs new file mode 100644 index 0000000..5590ab5 --- /dev/null +++ b/NW4RTools/BrresWriter.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +using NW4RTools.Models; + +namespace NW4RTools { + public class BrresWriter { + public static byte[] WriteFile(ResFile file) { + return new BrresWriter().Save(file); + } + + + + private ResFile File; + private ILogger Debug; + private SortedDictionary<int, string> OffsetMap; + private OutputStream Output; + + private BrresWriter() { + Debug = new ConsoleLogger(); + OffsetMap = new SortedDictionary<int, string>(); + } + + private byte[] Save(ResFile file) { + Output = new OutputStream(ByteEndian.BigEndian); + File = file; + + using (var c = Debug.Push("Offset Calculation")) + CalculateRoot(); + + Output.WriteBytes(StringTableData.GetBuffer()); + + return Output.GetBuffer(); + } + + // OK, here's how I'm going to code this: kinda like how BrawlLib works, first I'll calculate the size of + // each written element, and use that to build up a list of offsets. Then, I'll actually write out the data. + // This code will also handle building the string table. + + #region Offset/String Table Calculation + private int CurrentPos; + + private void CalculateRoot() { + // Where it all starts! + InitialiseStringTable(); + + // First up: BRRES header + CurrentPos = 0x10; + + // First block, and ResDict + CurrentPos += 8; + CurrentPos += GetSizeForResDict(File); + + // Now do each ResDict in the File + foreach (object dict in File.Values) { + CurrentPos += GetSizeForResDict(dict as ResDict<object>); + } + + // OK, so that's done. Process each type + foreach (var name in File.Keys) { + AddString(name); + switch (name) { + case "3DModels(NW4R)": + // do that stuff + break; + default: + Debug.Send("[[ UNIMPLEMENTED {0} ]]", name); + break; + } + } + + // ... and done with that. Build the string table and go! + CalculateStringTable(); + } + + + private int GetSizeForResDict(ResDict<object> dict) { + return 8 + ((dict.Count + 1) * 0x10); + } + + #endregion + + #region String Table Handling + // Contains the strings while they're being pulled from the ResFile data + private List<string> StringTable; + + // Once every string used in the .brres is found, CalculateStringTable() is called, which + // writes the table to an OutputStream and saves every offset + private Dictionary<string, int> StringTableOffsets; + + private OutputStream StringTableData; + + + // Called at the start of the process + private void InitialiseStringTable() { + StringTable = new List<string>(); + } + + private void AddString(string str) { + if (!StringTable.Contains(str)) { + StringTable.Add(str); + } + } + + private void CalculateStringTable() { + StringTable.Sort(); + + StringTableOffsets = new Dictionary<string, int>(); + StringTableData = new OutputStream(ByteEndian.BigEndian); + + foreach (var s in StringTable) { + // Add 4 because the Names are referenced by the string data, and not by the ResName struct itself + StringTableOffsets[s] = StringTableData.Position + 4; + StringTableData.WriteName(s); + } + } + #endregion + } +} + |