diff --git a/Transform.sln b/Transform.sln
new file mode 100644
index 0000000..76cc243
--- /dev/null
+++ b/Transform.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.10
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Transform", "Transform\Transform.csproj", "{0E2926CE-0052-46FD-91E4-A7CBF54726A5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0E2926CE-0052-46FD-91E4-A7CBF54726A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0E2926CE-0052-46FD-91E4-A7CBF54726A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0E2926CE-0052-46FD-91E4-A7CBF54726A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0E2926CE-0052-46FD-91E4-A7CBF54726A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Transform/App.config b/Transform/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/Transform/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Transform/Properties/AssemblyInfo.cs b/Transform/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..478c74e
--- /dev/null
+++ b/Transform/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Transform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Transform")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0e2926ce-0052-46fd-91e4-a7cbf54726a5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Transform/Transform.cs b/Transform/Transform.cs
new file mode 100644
index 0000000..4a280f0
--- /dev/null
+++ b/Transform/Transform.cs
@@ -0,0 +1,615 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Transform
+{
+ // Transform files because we can
+ public class Transform
+ {
+ ///
+ /// Main entry point into the program
+ ///
+ public static void Main(string[] args)
+ {
+ // Create the vars
+ TransformOperation operation = TransformOperation.None;
+ List files = new List();
+ string output = "interleaved.bin";
+
+ // If we have no args, complain
+ if (args.Length == 0)
+ {
+ Console.WriteLine("Need at least one argument");
+ Help();
+ return;
+ }
+
+ // Otherwise, we figure out what the heck we're dealing with
+ foreach (string arg in args)
+ {
+ switch(arg)
+ {
+ case "-?":
+ case "-h":
+ case "--help":
+ Help();
+ return;
+ case "-bi":
+ case "--bitswap":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.Bitswap;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-by":
+ case "--byteswap":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.Byteswap;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-w":
+ case "--wordswap":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.Wordswap;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-wb":
+ case "--wordbyteswap":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.WordByteswap;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-inb":
+ case "--inter-byte":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.InterleaveByte;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-inw":
+ case "--inter-word":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.InterleaveWord;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-sb":
+ case "--split-byte":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.SplitOneByte;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-ss":
+ case "-sw":
+ case "--split-short":
+ case "--split-word":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.SplitTwoBytes;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-si":
+ case "--split-int":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.SplitFourBytes;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ case "-sl":
+ case "--split-long":
+ if (operation == TransformOperation.None)
+ {
+ operation = TransformOperation.SplitEightBytes;
+ }
+ else
+ {
+ Console.Error.WriteLine("Only one transform flag allowed!");
+ Help();
+ return;
+ }
+ break;
+ default:
+ // If we have a file, add it as a valid input
+ if (File.Exists(arg))
+ {
+ files.Add(arg);
+ }
+ // If we have a directory, add all subfiles... ALL SUBFILES
+ else if (Directory.Exists(arg))
+ {
+ files.AddRange(Directory.EnumerateFiles(arg, "*", SearchOption.AllDirectories));
+ }
+ // If it's an output name, set that instead of interleaved
+ else if (arg.StartsWith("-out=") || arg.StartsWith("--out="))
+ {
+ output = String.Join("=", arg.Split('=').Skip(1));
+ }
+ // Otherwise, it's an invalid flag
+ else
+ {
+ Console.Error.WriteLine("Invalid flag: {0}", arg);
+ Help();
+ return;
+ }
+ break;
+ }
+ }
+
+ // If we found no files, complain
+ if (files.Count == 0)
+ {
+ Console.Error.WriteLine("Need at least one file");
+ Help();
+ return;
+ }
+
+ // If we have the interleave operation, we need at least 2 files
+ if ((operation == TransformOperation.InterleaveByte || operation == TransformOperation.InterleaveWord) && files.Count < 2)
+ {
+ Console.Error.WriteLine("Interleaving requires at least 2 files");
+ Help();
+ return;
+ }
+
+ // If we have the interleave operation, run that separately
+ if (operation == TransformOperation.InterleaveByte || operation == TransformOperation.InterleaveWord)
+ {
+ InterleaveFiles(files, output, operation);
+ }
+
+ // If we have a split operation, run the operation on everything
+ else if (operation >= TransformOperation.SplitOneByte)
+ {
+ foreach (string file in files)
+ {
+ SplitFile(file, operation);
+ }
+ }
+
+ // Otherwise, let's run the operation on EVERY SINGLE FILE
+ else
+ {
+ foreach (string file in files)
+ {
+ TransformFile(file, file + ".new", operation);
+ }
+ }
+ }
+
+ ///
+ /// Show the generic help text
+ ///
+ private static void Help()
+ {
+ Console.WriteLine(@"Transform - Transform files using standard operations
+-------------------------------------
+Usage: Transform.exe [-bi | -by | -w | -b] ...
+
+-?, -h, --help Show this help
+-bi, --bitswap Bitswap the inputs
+-by, --byteswap Byteswap the inputs
+-w, --wordswap Wordswap the inputs
+-wb, --wordbyteswap Word-byteswap the inputs
+-inb, --inter-byte Interleave inputs by byte
+ -out=, --out= Replace the default output name
+-inw, --inter-word Interleave inputs by word
+ -out=, --out= Replace the default output name
+-sb, --split-byte Split inputs by byte (even/odd)
+-ss, --split-short Split inputs by 2-byte short (even/odd)
+-sw, --split-word Split inputs by 2-byte word (even/odd)
+-si, --split-int Split inputs by 4-byte ints (even/odd)
+-sl, --split-long Split inputs by 8-byte longs (even/odd)
+");
+ }
+
+ ///
+ /// Determines the header skip operation
+ ///
+ private enum TransformOperation
+ {
+ // Default
+ None = 0,
+
+ // Swaping operations
+ Bitswap,
+ Byteswap,
+ Wordswap,
+ WordByteswap,
+
+ // Interleaving operations
+ InterleaveByte,
+ InterleaveWord,
+
+ // Splitting operations
+ SplitOneByte,
+ SplitTwoBytes,
+ SplitFourBytes,
+ SplitEightBytes,
+ }
+
+ ///
+ /// Interleave a set of files together to a single file
+ ///
+ /// List of valid files as inputs
+ /// Name of the output file
+ /// Either InterleaveByte or InterleaveWord
+ /// True if the files were interleaved successfully, false otherwise
+ private static bool InterleaveFiles(List inputs, string output, TransformOperation operation)
+ {
+ // If the inputs are empty, return
+ if (inputs.Count == 0)
+ {
+ return false;
+ }
+
+ // If we don't have at least 2 files, return
+ if (inputs.Count < 2)
+ {
+ return false;
+ }
+
+ // If we don't have a proper operation, return
+ if (operation != TransformOperation.InterleaveByte && operation != TransformOperation.InterleaveWord)
+ {
+ return false;
+ }
+
+ // Get the number of bytes to read
+ int bytecount = 0;
+ if (operation == TransformOperation.InterleaveByte)
+ {
+ bytecount = 1;
+ }
+ else if (operation == TransformOperation.InterleaveWord)
+ {
+ bytecount = 2;
+ }
+
+ // Get a list of file streams from the inputs
+ List readers = new List();
+ foreach (string input in inputs)
+ {
+ if (!File.Exists(input))
+ {
+ Console.WriteLine(input + " is not a valid file, exiting");
+ return false;
+ }
+ readers.Add(new BinaryReader(File.OpenRead(input)));
+ }
+
+ // Open the output file
+ var writer = new BinaryWriter(File.Open(output, FileMode.Create, FileAccess.Write));
+
+ // Write the input files and sizes to the console
+ for (int i = 0; i < inputs.Count; i++)
+ {
+ Console.WriteLine(inputs[i] + ": " + readers[i].BaseStream.Length);
+ }
+
+ // For each file, read and then write to the output
+ while (readers[0].BaseStream.Position < readers[0].BaseStream.Length)
+ {
+ foreach (var reader in readers)
+ {
+ writer.Write(reader.ReadBytes(bytecount));
+ }
+ }
+
+ writer.Dispose();
+ foreach (var reader in readers)
+ {
+ reader.Dispose();
+ }
+
+ return true;
+ }
+
+ ///
+ /// Split a file either on byte or word
+ ///
+ /// Input file name
+ /// Split*Bytes operations
+ ///
+ private static bool SplitFile(string input, TransformOperation operation)
+ {
+ // If the input is null, retrn
+ if (input == null)
+ {
+ return false;
+ }
+
+ // If the input isn't a file, return
+ if (!File.Exists(input))
+ {
+ return false;
+ }
+
+ // If the transform operation isn't a recognized one, return
+ if (operation < TransformOperation.SplitOneByte)
+ {
+ return false;
+ }
+
+ // Get the count we need for bytes to read before swapping
+ int bytecount = 0;
+ if (operation == TransformOperation.SplitOneByte)
+ {
+ bytecount = 1;
+ }
+ else if (operation == TransformOperation.SplitTwoBytes)
+ {
+ bytecount = 2;
+ }
+ else if (operation == TransformOperation.SplitFourBytes)
+ {
+ bytecount = 4;
+ }
+ else if (operation == TransformOperation.SplitEightBytes)
+ {
+ bytecount = 8;
+ }
+
+ // Open the input file and create two outputs, one for odd and one for even
+ FileStream inputStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ FileStream evenStream = File.Open(input + ".even", FileMode.Create, FileAccess.Write);
+ FileStream oddStream = File.Open(input + ".odd", FileMode.Create, FileAccess.Write);
+
+ // Now get the binary readers and writers
+ BinaryReader bri = new BinaryReader(inputStream);
+ BinaryWriter bwe = new BinaryWriter(evenStream);
+ BinaryWriter bwo = new BinaryWriter(oddStream);
+
+ // Now we loop and flip as we go
+ bool even = true;
+ while (bri.BaseStream.Position < inputStream.Length)
+ {
+ // If we're writing to even
+ if (even)
+ {
+ bwe.Write(bri.ReadBytes(bytecount));
+ bwe.Flush();
+ }
+ // Otherwise writing to odd
+ else
+ {
+ bwo.Write(bri.ReadBytes(bytecount));
+ bwo.Flush();
+ }
+
+ even = !even;
+ }
+
+ // Finally dispose of the readers and writers
+ bri.Dispose();
+ bwe.Dispose();
+ bwo.Dispose();
+
+ return true;
+ }
+
+ ///
+ /// Transform an input file using the given rule
+ ///
+ /// Input file name
+ /// Output file name
+ /// Transform operation to carry out
+ /// True if the file was transformed properly, false otherwise
+ private static bool TransformFile(string input, string output, TransformOperation operation)
+ {
+ bool success = true;
+
+ // If the input file doesn't exist, fail
+ if (!File.Exists(input))
+ {
+ Console.Error.WriteLine("I'm sorry but '" + input + "' doesn't exist!");
+ return false;
+ }
+
+ // Create the output directory if it doesn't already
+ if (!Directory.Exists(Path.GetDirectoryName(Path.GetFullPath(output))))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(output));
+ }
+
+ try
+ {
+ FileStream inputStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ FileStream outputStream = File.Open(output, FileMode.Create, FileAccess.Write);
+ success = TransformStream(inputStream, outputStream, operation);
+
+ // If the output file has size 0, delete it
+ if (new FileInfo(output).Length == 0)
+ {
+ File.Delete(output);
+ success = false;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex);
+ }
+
+ return success;
+ }
+
+ ///
+ /// Transform an input stream using the given rule
+ ///
+ /// Input stream
+ /// Output stream
+ /// Transform operation to carry out
+ /// True if the underlying read stream should be kept open, false otherwise
+ /// True if the underlying write stream should be kept open, false otherwise
+ /// True if the file was transformed properly, false otherwise
+ private static bool TransformStream(Stream input, Stream output, TransformOperation operation, bool keepReadOpen = false, bool keepWriteOpen = false)
+ {
+ bool success = true;
+
+ // If the sizes are wrong for the values, fail
+ long extsize = input.Length;
+ if ((operation == TransformOperation.Bitswap && (extsize % 2) != 0)
+ || (operation == TransformOperation.Byteswap && (extsize % 4) != 0)
+ || (operation == TransformOperation.Bitswap && (extsize % 4) != 0))
+ {
+ Console.Error.WriteLine("The stream did not have the correct size to be transformed!");
+ return false;
+ }
+
+ // Now read the proper part of the file and apply the rule
+ BinaryWriter bw = null;
+ BinaryReader br = null;
+ try
+ {
+ bw = new BinaryWriter(output);
+ br = new BinaryReader(input);
+
+ // Seek to the beginning offset
+ br.BaseStream.Seek(0, SeekOrigin.Begin);
+
+ // Then read and apply the operation as you go
+ if (success)
+ {
+ byte[] buffer = new byte[4];
+ int pos = 0;
+ while (input.Position < input.Length)
+ {
+ byte b = br.ReadByte();
+ switch (operation)
+ {
+ case TransformOperation.Bitswap:
+ // http://stackoverflow.com/questions/3587826/is-there-a-built-in-function-to-reverse-bit-order
+ uint r = b;
+ int s = 7;
+ for (b >>= 1; b != 0; b >>= 1)
+ {
+ r <<= 1;
+ r |= (byte)(b & 1);
+ s--;
+ }
+ r <<= s;
+ buffer[pos] = (byte)r;
+ break;
+ case TransformOperation.Byteswap:
+ if (pos % 2 == 1)
+ {
+ buffer[pos - 1] = b;
+ }
+ if (pos % 2 == 0)
+ {
+ buffer[pos + 1] = b;
+ }
+ break;
+ case TransformOperation.Wordswap:
+ buffer[3 - pos] = b;
+ break;
+ case TransformOperation.WordByteswap:
+ buffer[(pos + 2) % 4] = b;
+ break;
+ case TransformOperation.None:
+ default:
+ buffer[pos] = b;
+ break;
+ }
+
+ // Set the buffer position to default write to
+ pos = (pos + 1) % 4;
+
+ // If we filled a buffer, flush to the stream
+ if (pos == 0)
+ {
+ bw.Write(buffer);
+ bw.Flush();
+ buffer = new byte[4];
+ }
+ }
+ // If there's anything more in the buffer, write only the left bits
+ for (int i = 0; i < pos; i++)
+ {
+ bw.Write(buffer[i]);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex.ToString());
+ return false;
+ }
+ finally
+ {
+ // If we're not keeping the read stream open, dispose of the binary reader
+ if (!keepReadOpen)
+ {
+ br?.Dispose();
+ }
+
+ // If we're not keeping the write stream open, dispose of the binary reader
+ if (!keepWriteOpen)
+ {
+ bw?.Dispose();
+ }
+ }
+
+ return success;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Transform/Transform.csproj b/Transform/Transform.csproj
new file mode 100644
index 0000000..9524248
--- /dev/null
+++ b/Transform/Transform.csproj
@@ -0,0 +1,52 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {0E2926CE-0052-46FD-91E4-A7CBF54726A5}
+ Exe
+ Transform
+ Transform
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file