public static void CreateNodes(RARC.FileNode n)
        {
            Console.WriteLine("Creating Node for " + n.NodeName);
            string dirName = n.NodeName;

            dirName = dirName.ToUpper();
            for (int c = 0; c < dirName.Length; c++)
            {
                if (c == 4)
                {
                    break;
                }
                nodes[numNodesDone].type = nodes[numNodesDone].type + dirName[c];
            }
            nodes[numNodesDone].filenameOffset = (uint)stringTable.Length;
            stringTable = stringTable + dirName.ToLower() + (char)0x00;
            int numFiles = n.Files.Count;

            nodes[numNodesDone].numFileEntries       = (ushort)(numFiles + 2);
            nodes[numNodesDone].firstFileEntryOffset = (uint)totalNumFilesAdded;

            dirName = n.NodeName;
            nodes[numNodesDone].foldernameHash = Hash(dirName);

            numNodesDone++;
        }
        public static int countRARCDirs(RARC.FileNode Root)
        {
            int count = 0;

            foreach (RARC.FileNode n in Root.ChildNodes)
            {
                Console.WriteLine("Node: " + n.NodeName);
                count++;
                count += countRARCDirs(n);
            }

            return(count);
        }
        public static void CreateEntries(RARC.FileNode Root)
        {
            CreateFileEntries(Root);
            CreateNodeEntries(Root);

            CreateDummyFiles();


            foreach (RARC.FileNode n in Root.ChildNodes)
            {
                CreateNodes(n);
                CreateEntries(n);
            }
        }
        public static int countRARCFiles(RARC.FileNode Root)
        {
            int count = 0;

            foreach (RARC.FileEntry f in Root.Files)
            {
                Console.WriteLine("File: " + f.FileName);
                count++;
            }

            foreach (RARC.FileNode n in Root.ChildNodes)
            {
                count += countRARCFiles(n);
            }

            return(count);
        }
        public static void CreateNodeEntries(RARC.FileNode Root)
        {
            foreach (RARC.FileNode n in Root.ChildNodes)
            {
                Console.WriteLine("Creating fileEntry for node " + n.NodeName);

                fileEntries[totalNumFilesAdded].id             = 0xFFFF;
                fileEntries[totalNumFilesAdded].unknown2       = 0x0200;
                fileEntries[totalNumFilesAdded].filenameOffset = (ushort)0xFFFE;
                string fileName = n.NodeName;
                fileEntries[totalNumFilesAdded].filenameHash = Hash(fileName);
                fileEntries[totalNumFilesAdded].dataOffset   = (uint)0xFFFE;
                fileEntries[totalNumFilesAdded].dataSize     = 0x10;

                totalNumFilesAdded++;
            }
        }
        public static void CreateFileEntries(RARC.FileNode Root)
        {
            foreach (RARC.FileEntry f in Root.Files)
            {
                Console.WriteLine("Creating fileEntry for " + f.FileName);
                fileEntries[totalNumFilesAdded].id = (ushort)totalNumFilesAdded;

                if (f.FileName.EndsWith(".szs"))//Check if szs file and use right.. marker?
                {
                    fileEntries[totalNumFilesAdded].unknown2 = 0x9500;
                }
                else
                {
                    fileEntries[totalNumFilesAdded].unknown2 = 0x1100;
                }

                fileEntries[totalNumFilesAdded].filenameOffset = (ushort)stringTable.Length;
                string fileName = f.FileName;
                stringTable = stringTable + fileName + (char)0x00;
                fileEntries[totalNumFilesAdded].filenameHash = Hash(fileName);

                fileEntries[totalNumFilesAdded].dataOffset = lengthOfDataTable;
                lengthOfDataTable += (uint)f.fileData.Length;
                //Pad the data table out so new files start at a 0-based address
                while ((lengthOfDataTable % 16) != 0)
                {
                    lengthOfDataTable++;
                }
                if ((lengthOfDataTable % 32) != 0)//Check the new address is a multiple of 32 and add 16 if not
                {
                    lengthOfDataTable += 16;
                }
                filesData[numFilesWithData] = f.fileData;

                fileEntries[totalNumFilesAdded].dataSize = (uint)f.fileData.Length;

                numFilesWithData++;
                totalNumFilesAdded++;
            }
        }
        public static void CompressRARC(string FullPath, RARC.FileNode Root)
        {
            Console.WriteLine("\n>> Compressing " + Root.NodeName + " to " + FullPath);
            string newFile = Root.NodeName;

            stringTable = CreateStringTable();            //Setup the string table

            int directoriesCount = countRARCDirs(Root);

            nodes = new Node[directoriesCount + 1];             //Add 1 for the ROOT node

            numNodesDone      = 0;
            numFilesWithData  = 0;
            lengthOfDataTable = 0;

            //Fill out the ROOT node
            nodes[0].type = "ROOT";

            nodes[0].filenameOffset = (uint)stringTable.Length;
            String rootDirName = newFile;

            stringTable = stringTable + rootDirName + (char)0x00;

            nodes[0].foldernameHash = Hash(rootDirName);

            nodes[0].numFileEntries = (ushort)(Root.Files.Count + Root.ChildNodes.Count + 2);

            nodes[0].firstFileEntryOffset = 0;

            numNodesDone++;             //One node is complete


            //Get the total number of subdirectories and files
            //string[] allFiles = Directory.GetFiles(args[0], "*", SearchOption.AllDirectories);
            //int numOfFilesAndDirs = allFiles.Length + directoriesCount;
            int filesCount        = countRARCFiles(Root);
            int numOfFilesAndDirs = filesCount + directoriesCount;

            //Now set up an array of FileEntrys(Taking into account the "." and ".." file entries for each folder
            fileEntries = new FileEntry[numOfFilesAndDirs + (directoriesCount * 2) + 2];
            Console.WriteLine("# fileEntries " + (numOfFilesAndDirs + (directoriesCount * 2) + 2));

            filesData          = new byte[filesCount][]; //Setup an array to store all the file data paths in
            totalNumFilesAdded = 0;                      //How many file entries have been done


            CreateEntries(Root);


            //Fill out the filename & data offsets for the folder entries with the offset from the appropriate Node
            for (int n = 0; n < totalNumFilesAdded; n++)
            {
                if (fileEntries[n].filenameOffset == 0xFFFE)
                {
                    uint nodeNum = 0;
                    foreach (Node node in nodes)
                    {
                        if (node.foldernameHash == fileEntries[n].filenameHash)
                        {
                            fileEntries[n].filenameOffset = (ushort)node.filenameOffset;
                            fileEntries[n].dataOffset     = nodeNum;
                        }
                        nodeNum++;
                    }
                }
            }

            //Make the data table a mutiple of 16
            int numOfPaddingBytes = 0;

            while ((lengthOfDataTable % 16) != 0)
            {
                lengthOfDataTable++;
                numOfPaddingBytes++;
            }

            //Fill out Header information
            RarcHeader header = new RarcHeader();

            header.type             = "RARC";
            header.numFiles1        = (uint)totalNumFilesAdded;
            header.numFiles2        = (ushort)totalNumFilesAdded;
            header.sizeOfDataTable1 = lengthOfDataTable;
            header.sizeOfDataTable2 = lengthOfDataTable;
            header.unknown1         = 0x20;
            header.unknown6         = 0x20;
            header.unknown8         = 0x100;

            header.fileEntriesOffset = (numNodesDone * 16) + 0x20;
            if ((header.fileEntriesOffset % 32) != 0)            //Check if it's a multiple of 32 and make it one if it's not
            {
                header.fileEntriesOffset += 16;
            }

            Console.WriteLine("fileEntriesOffset is: " + header.fileEntriesOffset);
            Console.WriteLine("totalNumFilesAdded: " + (totalNumFilesAdded + 1));
            header.numNodes = numNodesDone;

            int numFileEntries = (numOfFilesAndDirs + (directoriesCount * 2) + 2);

            int x = 0;

            while (0 != (((numFileEntries) * 20) + x) % 16)
            {
                x++;
            }

            header.stringTableOffset = header.fileEntriesOffset + (uint)((numFileEntries * 20) + x);
            if ((header.stringTableOffset % 32) != 0)            //Check if it's a multiple of 32 and make it one if it's not
            {
                header.stringTableOffset += 16;
            }

            Console.WriteLine("stringTableOffset is: " + header.stringTableOffset);

            while (0 != (stringTable.Length) % 16)            //Pad out the string table so the data table starts at a 0based address
            {
                stringTable = stringTable + (char)0x00;
            }

            header.dataStartOffset = (uint)(header.stringTableOffset + stringTable.Length);
            if ((header.dataStartOffset % 32) != 0)            //Check if it's a multiple of 32 and make it one if it's not
            {
                header.dataStartOffset += 16;
            }

            Console.WriteLine("dataStartOffset is: " + header.dataStartOffset);


            header.sizeOfStringTable = (uint)stringTable.Length;
            header.size = lengthOfDataTable + header.dataStartOffset + 0x20;

            //Let's write it out

            // Uncomment while testing
            //FullPath += ".new.arc";

            FileStream   filestreamWriter = new FileStream(FullPath, FileMode.Create);
            BinaryWriter binWriter        = new BinaryWriter(filestreamWriter);

            Console.WriteLine("Writing to file: " + FullPath);
            Console.WriteLine("Writing header...");
            //First the Header is written
            binWriter.Write(header.type[0]);
            binWriter.Write(header.type[1]);
            binWriter.Write(header.type[2]);
            binWriter.Write(header.type[3]);

            byte[] buffer = BitConverter.GetBytes(header.size);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown1);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.dataStartOffset);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.sizeOfDataTable1);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.sizeOfDataTable2);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown4);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown5);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.numNodes);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown6);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.numFiles1);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.fileEntriesOffset);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);


            buffer = BitConverter.GetBytes(header.sizeOfStringTable);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.stringTableOffset);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.numFiles2);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown8);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            buffer = BitConverter.GetBytes(header.unknown9);
            Array.Reverse(buffer);
            filestreamWriter.Write(buffer, 0, buffer.Length);

            Console.WriteLine("Writing nodes...");
            //Write each of the nodes
            foreach (Node currentNode in nodes)
            {
                Console.WriteLine("Writing " + currentNode.type);
                binWriter.Write(currentNode.type[0]);
                if (currentNode.type.Length > 1)                       //Incase the dirname is only 1 char long
                {
                    binWriter.Write(currentNode.type[1]);
                }
                else
                {
                    filestreamWriter.WriteByte(0x20);
                }
                if (currentNode.type.Length > 2)                       //Incase the dirname is only 2 char long
                {
                    binWriter.Write(currentNode.type[2]);
                }
                else
                {
                    filestreamWriter.WriteByte(0x20);
                }
                if (currentNode.type.Length == 4)                       //Incase the dirname is only 3 char long
                {
                    binWriter.Write(currentNode.type[3]);
                }
                else
                {
                    filestreamWriter.WriteByte(0x20);
                }

                buffer = BitConverter.GetBytes(currentNode.filenameOffset);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);
                buffer = BitConverter.GetBytes(currentNode.foldernameHash);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);
                buffer = BitConverter.GetBytes(currentNode.numFileEntries);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);
                buffer = BitConverter.GetBytes(currentNode.firstFileEntryOffset);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);
            }

            //Pad out the file to get the file entries at their correct offset
            while (filestreamWriter.Position < (header.fileEntriesOffset + 32))
            {
                filestreamWriter.WriteByte(0x00);
            }

            //Write all the file entries
            foreach (FileEntry entry in fileEntries)
            {
                Console.WriteLine(String.Format("Writing fileEntry {0:X6}", entry.filenameOffset));

                buffer = BitConverter.GetBytes(entry.id);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.filenameHash);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.unknown2);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.filenameOffset);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.dataOffset);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.dataSize);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(entry.zero);
                Array.Reverse(buffer);
                filestreamWriter.Write(buffer, 0, buffer.Length);
            }

            //Pad out the file to get the string table at its correct offset

            while (filestreamWriter.Position < (header.stringTableOffset + 32))
            {
                filestreamWriter.WriteByte(0x00);
            }

            //Write string table
            Encoding enc = Encoding.UTF8;

            binWriter.Write(enc.GetBytes(stringTable));

            //Pad out the file to get the data table at its correct offset
            while (filestreamWriter.Position < (header.dataStartOffset + 32))
            {
                filestreamWriter.WriteByte(0x00);
            }

            //Write files data
            foreach (byte[] file in filesData)
            {
                Console.WriteLine("Dumping file data...");
                buffer = file;
                filestreamWriter.Write(buffer, 0, buffer.Length);
                while ((filestreamWriter.Position % 32) != 0)                //Pad out the data so the next file begins on a 0-based multiple of 32
                {
                    filestreamWriter.WriteByte(0x00);
                }
            }
            for (int pad = 0; pad < numOfPaddingBytes; pad++)            //Write the bytes neccessary to make the entire file divisble by 32
            {
                filestreamWriter.WriteByte(0x00);
            }

            binWriter.Close();
            filestreamWriter.Close();

            Console.WriteLine("Packed and good to go!");
        }