From 250a30907121f32ec45fb33bfca9bb812a3e639a Mon Sep 17 00:00:00 2001
From: Chev <11602755+chev2@users.noreply.github.com>
Date: Sat, 16 Jan 2021 22:37:29 -0800
Subject: [PATCH] Update SARC.cs
Remove ReadFile method, add ToBytes method, add WriteFiles method. FromBytes uses a byte array instead of memory stream.
---
 botw-toolset/IO/SARC/SARC.cs | 83 +++++++++++++++++++++++++++---------
 1 file changed, 62 insertions(+), 21 deletions(-)
diff --git a/botw-toolset/IO/SARC/SARC.cs b/botw-toolset/IO/SARC/SARC.cs
index 4d84835..299085a 100644
--- a/botw-toolset/IO/SARC/SARC.cs
+++ b/botw-toolset/IO/SARC/SARC.cs
@@ -37,15 +37,15 @@ namespace BOTWToolset.IO.SARC
         public byte[][] Files;
 
         /// 
-        /// Gets a  from a data stream.
+        /// Gets a  from an array of bytes.
         /// 
-        /// Data stream to get  info from.
+        /// Array of bytes to get  info from.
         ///  with the stream's data.
-        public static SARC FromBytes(Stream stream)
+        public static SARC FromBytes(byte[] bytes)
         {
             SARC s = new SARC();
 
-            using (var r = new BinaryReaderBig(stream))
+            using (var r = new BinaryReaderBig(new MemoryStream(bytes)))
             {
                 //SARC header
                 s.Magic = new string(r.ReadChars(4));
@@ -159,26 +159,69 @@ namespace BOTWToolset.IO.SARC
             return s;
         }
 
-        public static SARC ReadFile(string file)
-        {
-            if (File.Exists(file))
-            {
-                return FromBytes(File.Open(file, FileMode.Open));
-            }
-            else
-            {
-                throw new FileNotFoundException("Cannot find SARC file to read.");
-            }
-        }
-
-        public static byte[] GetBytes(SARC sarc)
+        /// 
+        /// Gets an array of bytes from a .
+        /// 
+        ///  to convert to bytes.
+        /// byte[] containg the  data.
+        public static byte[] ToBytes(SARC sarc)
         {
             // TODO: Make this an actual function
             List bytes = new List();
 
+            // SARC header
+            bytes.AddRange(new byte[] { 0x53, 0x41, 0x52, 0x43 }); // SARC magic header
+            bytes.AddRange(new byte[] { 0x00, 0x14 }); // Header length, always 0x14
+            bytes.AddRange(new byte[] { 0xFE, 0xFF }); // 0xFEFF - big endian, 0xFFFE - little endian
+            bytes.AddRange(BitConverter.GetBytes(sarc.FileSize).Reverse()); // File size of the entire SARC, including headers
+            bytes.AddRange(BitConverter.GetBytes(sarc.DataOffset).Reverse()); // Beginning of data offset
+            bytes.AddRange(new byte[] { 0x01, 0x00 }); // Version number, always 0x0100
+            bytes.AddRange(new byte[] { 0x00, 0x00 }); // Reserved
+
+            // SFAT header
+            bytes.AddRange(new byte[] { 0x53, 0x46, 0x41, 0x54 }); // SFAT magic header
+            bytes.AddRange(new byte[] { 0x00, 0x0C }); // Header length, always 0xC
+            bytes.AddRange(BitConverter.GetBytes(sarc.SFAT.NodeCount).Reverse());
+            bytes.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x65 }); // Hash key, always 0x65
+
+            // SFAT node structures
+            foreach (SFATNode node in sarc.SFAT.Nodes)
+            {
+                bytes.AddRange(BitConverter.GetBytes(node.FileNameHash).Reverse());
+                bytes.AddRange(BitConverter.GetBytes(node.FileAttributes).Reverse());
+                bytes.AddRange(BitConverter.GetBytes(node.NodeFileDataBegin).Reverse());
+                bytes.AddRange(BitConverter.GetBytes(node.NodeFileDataEnd).Reverse());
+            }
+
+            // SFNT header
+            bytes.AddRange(new byte[] { 0x53, 0x46, 0x4E, 0x54 }); // SFNT magic header
+            bytes.AddRange(new byte[] { 0x00, 0x08 }); // Header length, always 0x8
+            bytes.AddRange(new byte[] { 0x00, 0x00 }); // Reserved
+
+            foreach (var filename in sarc.SFNT.FileNames)
+            {
+                var extra = filename.Length % 4; // Number of characters not in a 4-byte-aligned segment
+
+                for (int i = 0; i < filename.Length + (4 - extra); i++)
+                {
+                    if (i < filename.Length) // If this is a valid char
+                        bytes.Add((byte)filename[i]);
+                    else // If not, add null
+                        bytes.Add(0x00);
+                }
+            }
+
+            foreach (var file_bytes in sarc.Files)
+                bytes.AddRange(file_bytes);
+
             return bytes.ToArray();
         }
 
+        /// 
+        /// Writes a 's unpackaged files to a folder.
+        /// 
+        ///  to get file data from.
+        /// Folder to write the unpackaged files to.
         public static void WriteFiles(SARC sarc, string folder)
         {
             //TODO: Finish this function
@@ -191,10 +234,8 @@ namespace BOTWToolset.IO.SARC
                 // Get combined path (folder + file name)
                 var file_path = Path.Combine(folder, file_name);
 
-                using (var r = new BinaryWriterBig(File.OpenWrite(file_path), System.Text.Encoding.UTF8))
-                {
-
-                }
+                // Write bytes to file
+                File.WriteAllBytes(file_path, files[i]);
             }
         }
     }