From f19f94f45953a562b586261bea9ddb7ad1ad9e37 Mon Sep 17 00:00:00 2001
From: Chev <11602755+chev2@users.noreply.github.com>
Date: Sat, 16 Jan 2021 22:49:36 -0800
Subject: [PATCH] Update TSCB methods
FromBytes replaces ReadFile & uses a byte array instead of filename. GetBytes is renamed to ToBytes.
---
 botw-toolset/Control/TabTSCB.xaml.cs |   4 +-
 botw-toolset/IO/TSCB/TSCB.cs         | 267 +++++++++++++--------------
 2 files changed, 132 insertions(+), 139 deletions(-)
diff --git a/botw-toolset/Control/TabTSCB.xaml.cs b/botw-toolset/Control/TabTSCB.xaml.cs
index 9ce25fd..18b9450 100644
--- a/botw-toolset/Control/TabTSCB.xaml.cs
+++ b/botw-toolset/Control/TabTSCB.xaml.cs
@@ -306,7 +306,7 @@ namespace BOTWToolset.Control
 
                 BOTWConsole.Log("Opening file");
 
-                TSCB t = TSCB.ReadFile(openFileDialog.FileName);
+                TSCB t = TSCB.FromBytes(File.ReadAllBytes(openFileDialog.FileName));
 
                 // Set the current file location to the chosen file's location
                 fileLocation = openFileDialog.FileName;
@@ -365,7 +365,7 @@ namespace BOTWToolset.Control
 
             if ((bool)saveFileDialog.ShowDialog())
             {
-                File.WriteAllBytes(saveFileDialog.FileName, TSCB.GetBytes(currentTSCB));
+                File.WriteAllBytes(saveFileDialog.FileName, TSCB.ToBytes(currentTSCB));
             }
         }
 
diff --git a/botw-toolset/IO/TSCB/TSCB.cs b/botw-toolset/IO/TSCB/TSCB.cs
index 5a9674e..18a36a9 100644
--- a/botw-toolset/IO/TSCB/TSCB.cs
+++ b/botw-toolset/IO/TSCB/TSCB.cs
@@ -52,168 +52,161 @@ namespace BOTWToolset.IO.TSCB
         /// 
         /// The .tscb file.
         /// 
-        public static TSCB ReadFile(string file)
+        public static TSCB FromBytes(byte[] bytes)
         {
-            if (File.Exists(file))
+            TSCB t = new TSCB();
+
+            // Use big-endian
+            using (var r = new BinaryReaderBig(new MemoryStream(bytes)))
             {
-                TSCB t = new TSCB();
+                // Set header info from file on the new TSCBInfo
+                t.Signature = new string(r.ReadChars(4));
+                t.Version = r.ReadByte();
 
-                // Use big-endian
-                using (var r = new BinaryReaderBig(File.Open(file, FileMode.Open)))
+                // Skip the 3 extra version bytes
+                r.BaseStream.Seek(3, SeekOrigin.Current);
+
+                // Skip 4 bytes of "00 00 00 01"
+                r.BaseStream.Seek(4, SeekOrigin.Current);
+
+                t.FileBaseOffset = r.ReadUInt32();
+                t.WorldScale = r.ReadSingle();
+                t.TerrainMaxHeight = r.ReadSingle();
+                t.MaterialInfoLength = r.ReadUInt32();
+                t.AreaArrayLength = r.ReadUInt32();
+
+                // Skip 8 bytes of padding
+                r.Advance(8);
+
+                t.TileSize = r.ReadSingle();
+
+                // Skip 4 bytes of "00 00 00 08"
+                r.Advance(4);
+
+                // Read mat info offsets
+                t.MaterialInfoOffsets = r.ReadBytes((int)((t.MaterialInfoLength * 4) + 4));
+
+                BOTWConsole.Log($"Offset before material iteration: {r.BaseStream.Position}");
+
+                // Initialize mat info array with provided length
+                t.MaterialInfo = new MaterialInfo[t.MaterialInfoLength];
+
+                // Initialize every mat info, then add to the array
+                for (int i = 0; i < t.MaterialInfoLength; i++)
                 {
-                    // Set header info from file on the new TSCBInfo
-                    t.Signature = new string(r.ReadChars(4));
-                    t.Version = r.ReadByte();
+                    uint index = r.ReadUInt32();
+                    float tex_u = r.ReadSingle();
+                    float tex_v = r.ReadSingle();
+                    float unk_1 = r.ReadSingle();
+                    float unk_2 = r.ReadSingle();
 
-                    // Skip the 3 extra version bytes
-                    r.BaseStream.Seek(3, SeekOrigin.Current);
+                    MaterialInfo matInfo = new MaterialInfo(index, tex_u, tex_v, unk_1, unk_2);
 
-                    // Skip 4 bytes of "00 00 00 01"
-                    r.BaseStream.Seek(4, SeekOrigin.Current);
+                    t.MaterialInfo[i] = matInfo;
+                }
 
-                    t.FileBaseOffset = r.ReadUInt32();
-                    t.WorldScale = r.ReadSingle();
-                    t.TerrainMaxHeight = r.ReadSingle();
-                    t.MaterialInfoLength = r.ReadUInt32();
-                    t.AreaArrayLength = r.ReadUInt32();
+                BOTWConsole.Log($"Offset before area offset iteration: {r.BaseStream.Position}");
 
-                    // Skip 8 bytes of padding
-                    r.Advance(8);
+                // Read area offsets
+                t.AreaArrayOffsets = r.ReadBytes((int)(t.AreaArrayLength * 4));
 
-                    t.TileSize = r.ReadSingle();
+                BOTWConsole.Log($"Offset before area iteration: {r.BaseStream.Position}");
 
-                    // Skip 4 bytes of "00 00 00 08"
-                    r.Advance(4);
+                t.AreaInfo = new AreaInfo[t.AreaArrayLength];
 
-                    // Read mat info offsets
-                    t.MaterialInfoOffsets = r.ReadBytes((int)((t.MaterialInfoLength * 4) + 4));
+                // Read every area info entry
+                for (int i = 0; i < t.AreaArrayLength; i++)
+                {
+                    uint offset = (uint)r.BaseStream.Position;
 
-                    BOTWConsole.Log($"Offset before material iteration: {r.BaseStream.Position}");
+                    float xpos = r.ReadSingle();
+                    float zpos = r.ReadSingle();
+                    float area_size = r.ReadSingle();
+                    float min_terrain_height = r.ReadSingle();
+                    float max_terrain_height = r.ReadSingle();
+                    float min_water_height = r.ReadSingle();
+                    float max_water_height = r.ReadSingle();
+                    uint unk_1 = r.ReadUInt32();
 
-                    // Initialize mat info array with provided length
-                    t.MaterialInfo = new MaterialInfo[t.MaterialInfoLength];
+                    if (unk_1 == 0)
+                    { // If this unknown is equal to 0, skip the extra byte coming after it
+                        uint next_val = r.ReadUInt32();
 
-                    // Initialize every mat info, then add to the array
-                    for (int i = 0; i < t.MaterialInfoLength; i++)
-                    {
-                        uint index = r.ReadUInt32();
-                        float tex_u = r.ReadSingle();
-                        float tex_v = r.ReadSingle();
-                        float unk_1 = r.ReadSingle();
-                        float unk_2 = r.ReadSingle();
-
-                        MaterialInfo matInfo = new MaterialInfo(index, tex_u, tex_v, unk_1, unk_2);
-
-                        t.MaterialInfo[i] = matInfo;
-                    }
-
-                    BOTWConsole.Log($"Offset before area offset iteration: {r.BaseStream.Position}");
-
-                    // Read area offsets
-                    t.AreaArrayOffsets = r.ReadBytes((int)(t.AreaArrayLength * 4));
-
-                    BOTWConsole.Log($"Offset before area iteration: {r.BaseStream.Position}");
-
-                    t.AreaInfo = new AreaInfo[t.AreaArrayLength];
-
-                    // Read every area info entry
-                    for (int i = 0; i < t.AreaArrayLength; i++)
-                    {
-                        uint offset = (uint)r.BaseStream.Position;
-
-                        float xpos = r.ReadSingle();
-                        float zpos = r.ReadSingle();
-                        float area_size = r.ReadSingle();
-                        float min_terrain_height = r.ReadSingle();
-                        float max_terrain_height = r.ReadSingle();
-                        float min_water_height = r.ReadSingle();
-                        float max_water_height = r.ReadSingle();
-                        uint unk_1 = r.ReadUInt32();
-
-                        if (unk_1 == 0)
-                        { // If this unknown is equal to 0, skip the extra byte coming after it
-                            uint next_val = r.ReadUInt32();
-
-                            if (next_val != 1) // If the next value isn't extra unneeded info
-                            {
-                                r.Advance(-4);
-                            }
-                        }
-
-                        uint file_base = r.ReadUInt32();
-                        uint unk_2 = r.ReadUInt32();
-                        uint unk_3 = r.ReadUInt32();
-                        uint ref_extra = r.ReadUInt32();
-
-                        AreaInfo areaInfo = new AreaInfo
-                        {
-                            PositionX = xpos,
-                            PositionZ = zpos,
-                            AreaSize = area_size,
-                            MinTerrainHeight = min_terrain_height,
-                            MaxTerrainHeight = max_terrain_height,
-                            MinWaterHeight = min_water_height,
-                            MaxWaterHeight = max_water_height,
-                            Unknown1 = unk_1,
-                            FileBase = file_base,
-                            Unknown2 = unk_2,
-                            Unknown3 = unk_3,
-                            ReferenceExtra = ref_extra,
-                            Offset = offset
-                        };
-
-                        areaInfo.ExtraInfoLength = r.ReadUInt32(); //Usually 0, 4, or 8
-
-                        if (ref_extra == 4)
-                        {
-                            if (areaInfo.ExtraInfoLength == 8)
-                            { //Skip the extra "20" after the 8, as well as the extra info
-                                areaInfo.HasGrass = true;
-                                areaInfo.HasWater = true;
-                                r.Advance(36);
-                            }
-                            else //If the length is 4
-                            {
-                                var bytes = r.ReadBytes(16).ToArray();
-                                if (bytes[7] == 0) //If byte 7 equals 0
-                                    areaInfo.HasGrass = true;
-                                else //Else if the 2nd byte should be anything else (should always be 1)
-                                    areaInfo.HasWater = true;
-                            }
-                        }
-                        else //If the extra info flags aren't set, go back 4
+                        if (next_val != 1) // If the next value isn't extra unneeded info
                         {
                             r.Advance(-4);
                         }
-
-                        t.AreaInfo[i] = areaInfo;
                     }
 
-                    BOTWConsole.Log($"Offset after area iteration: {r.BaseStream.Position} (should be {t.FileBaseOffset + 16})");
+                    uint file_base = r.ReadUInt32();
+                    uint unk_2 = r.ReadUInt32();
+                    uint unk_3 = r.ReadUInt32();
+                    uint ref_extra = r.ReadUInt32();
 
-                    //Get the number of filenames by getting how many bytes they take up out of the entire file size
-                    var filenames_count = (r.BaseStream.Length - (t.FileBaseOffset + 16)) / 12;
-
-                    BOTWConsole.Log($"Filename count: {filenames_count} (should be {t.AreaArrayLength})");
-
-                    t.FileNames = new string[filenames_count];
-
-                    r.BaseStream.Seek(t.FileBaseOffset + 16, SeekOrigin.Begin); // TODO: change this to 'current' later, or maybe even remove
-
-                    for (int i = 0; i < filenames_count; i++)
+                    AreaInfo areaInfo = new AreaInfo
                     {
-                        string filename = new string(r.ReadChars(12));
+                        PositionX = xpos,
+                        PositionZ = zpos,
+                        AreaSize = area_size,
+                        MinTerrainHeight = min_terrain_height,
+                        MaxTerrainHeight = max_terrain_height,
+                        MinWaterHeight = min_water_height,
+                        MaxWaterHeight = max_water_height,
+                        Unknown1 = unk_1,
+                        FileBase = file_base,
+                        Unknown2 = unk_2,
+                        Unknown3 = unk_3,
+                        ReferenceExtra = ref_extra,
+                        Offset = offset
+                    };
 
-                        t.FileNames[i] = filename;
+                    areaInfo.ExtraInfoLength = r.ReadUInt32(); //Usually 0, 4, or 8
+
+                    if (ref_extra == 4)
+                    {
+                        if (areaInfo.ExtraInfoLength == 8)
+                        { //Skip the extra "20" after the 8, as well as the extra info
+                            areaInfo.HasGrass = true;
+                            areaInfo.HasWater = true;
+                            r.Advance(36);
+                        }
+                        else //If the length is 4
+                        {
+                            var areabytes = r.ReadBytes(16).ToArray();
+                            if (areabytes[7] == 0) //If byte 7 equals 0
+                                areaInfo.HasGrass = true;
+                            else //Else if the 2nd byte should be anything else (should always be 1)
+                                areaInfo.HasWater = true;
+                        }
                     }
+                    else //If the extra info flags aren't set, go back 4
+                    {
+                        r.Advance(-4);
+                    }
+
+                    t.AreaInfo[i] = areaInfo;
                 }
 
-                return t;
-            }
-            else
-            {
-                throw new FileNotFoundException("Cannot find .tscb file to read.");
+                BOTWConsole.Log($"Offset after area iteration: {r.BaseStream.Position} (should be {t.FileBaseOffset + 16})");
+
+                //Get the number of filenames by getting how many bytes they take up out of the entire file size
+                var filenames_count = (r.BaseStream.Length - (t.FileBaseOffset + 16)) / 12;
+
+                BOTWConsole.Log($"Filename count: {filenames_count} (should be {t.AreaArrayLength})");
+
+                t.FileNames = new string[filenames_count];
+
+                r.BaseStream.Seek(t.FileBaseOffset + 16, SeekOrigin.Begin); // TODO: change this to 'current' later, or maybe even remove
+
+                for (int i = 0; i < filenames_count; i++)
+                {
+                    string filename = new string(r.ReadChars(12));
+
+                    t.FileNames[i] = filename;
+                }
             }
+
+            return t;
         }
 
         /// 
@@ -221,7 +214,7 @@ namespace BOTWToolset.IO.TSCB
         /// 
         ///  that contains data to write.
         /// Byte array containing the TSCB data.
-        public static byte[] GetBytes(TSCB tscb)
+        public static byte[] ToBytes(TSCB tscb)
         {
             List b = new List();