summaryrefslogtreecommitdiff
path: root/NW4RTools/BrresWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'NW4RTools/BrresWriter.cs')
-rw-r--r--NW4RTools/BrresWriter.cs121
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
+ }
+}
+