Example #1
0
        private void addEntry(string nodePath, byte[] fileData)
        {
            //Parse path
            if (nodePath.StartsWith("/")) nodePath = nodePath.Remove(0, 1);
            string[] path = nodePath.Split('/'); //Last entry is the filename

            int nodeIndex = -1;
            int maxIndex = (u8Nodes.Count > 0) ? u8Nodes.Count - 1 : 0;
            int currentIndex = 0;
            List<int> pathIndices = new List<int>();

            for (int i = 0; i < path.Length - 1; i++)
            {
                for (int j = currentIndex; j <= maxIndex; j++)
                {
                    if (stringTable[j].ToLower() == path[i].ToLower())
                    {
                        if (i == path.Length - 2) nodeIndex = j;

                        maxIndex = (int)u8Nodes[j].SizeOfData - 1;
                        currentIndex = j + 1;
                        pathIndices.Add(j);

                        break;
                    }

                    if (j == maxIndex - 1) throw new Exception("Path wasn't found!");
                }
            }

            //Get last entry in current dir
            int lastEntry;

            if (nodeIndex > -1) lastEntry = (int)u8Nodes[nodeIndex].SizeOfData - 2;
            else lastEntry = (rootNode.SizeOfData > 1) ? (int)rootNode.SizeOfData - 2 : -1;

            //Create and insert node + data
            U8_Node tempNode = new U8_Node();
            tempNode.Type = (fileData.Length == 0) ? U8_NodeType.Directory : U8_NodeType.File;
            tempNode.SizeOfData = (uint)((fileData.Length == 0) ? lastEntry + 2 : fileData.Length);
            tempNode.OffsetToData = (uint)((fileData.Length == 0) ? Shared.CountCharsInString(nodePath, '/') : 0);

            stringTable.Insert(lastEntry + 1, path[path.Length - 1]);
            u8Nodes.Insert(lastEntry + 1, tempNode);
            data.Insert(lastEntry + 1, fileData);

            //Update rootnode and path sizes (+1)
            rootNode.SizeOfData += 1;

            foreach (int index in pathIndices)
                if (u8Nodes[index].Type == U8_NodeType.Directory)
                    u8Nodes[index].SizeOfData += 1;

            for (int i = lastEntry + 1; i < u8Nodes.Count; i++)
                if (u8Nodes[i].Type == U8_NodeType.Directory)
                    u8Nodes[i].SizeOfData += 1;
        }
Example #2
0
        private void parseU8(Stream u8File)
        {
            fireDebug("Pasing U8 File...");

            u8Header = new U8_Header();
            rootNode = new U8_Node();
            u8Nodes = new List<U8_Node>();
            stringTable = new List<string>();
            data = new List<byte[]>();

            fireDebug("   Detecting Header...");
            headerType = Headers.DetectHeader(u8File);
            Headers.HeaderType tempType = headerType;

            fireDebug("    -> {0}", headerType.ToString());

            if (headerType == Headers.HeaderType.IMD5)
            {
                fireDebug("   Reading IMD5 Header...");
                header = Headers.IMD5.Load(u8File);

                byte[] file = new byte[u8File.Length];
                u8File.Read(file, 0, file.Length);

                MD5 m = MD5.Create();
                byte[] newHash = m.ComputeHash(file, (int)headerType, (int)u8File.Length - (int)headerType);
                m.Clear();

                if (!Shared.CompareByteArrays(newHash, ((Headers.IMD5)header).Hash))
                {
                    fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\");
                    fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!"));
                }
            }
            else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET)
            {
                fireDebug("   Reading IMET Header...");
                header = Headers.IMET.Load(u8File);

                if (!((Headers.IMET)header).HashesMatch)
                {
                    fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\");
                    fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!"));
                }
            }

            fireDebug("   Checking for Lz77 Compression...");
            if (Lz77.IsLz77Compressed(u8File))
            {
                fireDebug("    -> Lz77 Compression Found...");
                fireDebug("   Decompressing U8 Data...");

                Lz77 l = new Lz77();
                Stream decompressedFile = l.Decompress(u8File);

                tempType = Headers.DetectHeader(decompressedFile);
                u8File = decompressedFile;

                lz77 = true;
            }

            u8File.Seek((int)tempType, SeekOrigin.Begin);
            byte[] temp = new byte[4];

            //Read U8 Header
            fireDebug("   Reading U8 Header: Magic... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
            u8File.Read(temp, 0, 4);
            if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.U8Magic)
            { fireDebug("    -> Invalid Magic!"); throw new Exception("U8 Header: Invalid Magic!"); }

            fireDebug("   Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
            u8File.Read(temp, 0, 4);
            if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.OffsetToRootNode)
            { fireDebug("    -> Invalid Offset to Rootnode"); throw new Exception("U8 Header: Invalid Offset to Rootnode!"); }

            fireDebug("   Reading U8 Header: Header Size... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
            u8File.Read(temp, 0, 4);
            u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(temp, 0));

            fireDebug("   Reading U8 Header: Offset to Data... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
            u8File.Read(temp, 0, 4);
            u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0));

            u8File.Seek(16, SeekOrigin.Current);

            //Read Rootnode
            fireDebug("   Reading Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
            u8File.Read(temp, 0, 4);
            rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0));
            rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2));

            u8File.Read(temp, 0, 4);
            rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0));

            u8File.Read(temp, 0, 4);
            rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0));

            int stringTablePosition = (int)((int)tempType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12);
            int nodePosition = (int)u8File.Position;

            //Read Nodes
            for (int i = 0; i < rootNode.SizeOfData - 1; i++)
            {
                fireDebug("   Reading Node #{1} of {2}... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper(), i + 1, rootNode.SizeOfData - 1);
                fireProgress((int)((i + 1) * 100 / (rootNode.SizeOfData - 1)));

                U8_Node tempNode = new U8_Node();
                string tempName = string.Empty;
                byte[] tempData = new byte[0];

                //Read Node Entry
                u8File.Seek(nodePosition, SeekOrigin.Begin);

                fireDebug("    -> Reading Node Entry... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
                u8File.Read(temp, 0, 4);
                tempNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0));
                tempNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2));

                u8File.Read(temp, 0, 4);
                tempNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0));

                u8File.Read(temp, 0, 4);
                tempNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0));

                nodePosition = (int)u8File.Position;

                fireDebug("        -> {0}", tempNode.Type.ToString());

                //Read Node Name
                u8File.Seek(stringTablePosition + tempNode.OffsetToName, SeekOrigin.Begin);

                fireDebug("    -> Reading Node Name... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());
                for (;;)
                {
                    char tempChar = (char)u8File.ReadByte();
                    if (tempChar == 0x00) break;

                    tempName += tempChar;

                    if (tempName.Length > 255) break;
                }

                fireDebug("        -> {0}", tempName);

                //Read Node Data
                if (tempNode.Type == U8_NodeType.File)
                {
                    u8File.Seek((int)tempType + tempNode.OffsetToData, SeekOrigin.Begin);

                    fireDebug("    -> Reading Node Data (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper());

                    tempData = new byte[tempNode.SizeOfData];
                    u8File.Read(tempData, 0, tempData.Length);
                }

                if (tempName.ToLower() == "icon.bin") iconSize = getRealSize(tempData);
                else if (tempName.ToLower() == "banner.bin") bannerSize = getRealSize(tempData);
                else if (tempName.ToLower() == "sound.bin") soundSize = getRealSize(tempData);

                u8Nodes.Add(tempNode);
                stringTable.Add(tempName);
                data.Add(tempData);
            }

            fireDebug("Pasing U8 File Finished...");
        }
Example #3
0
        private void createFromDir(string path)
        {
            fireDebug("Creating U8 File from: {0}", path);

            if (path[path.Length - 1] != Path.DirectorySeparatorChar) path += Path.DirectorySeparatorChar;

            fireDebug("   Collecting Content...");
            string[] dirEntries = getDirContent(path, true);
            int offsetToName = 1;
            int offsetToData = 0;

            fireDebug("   Creating U8 Header...");
            u8Header = new U8_Header();
            rootNode = new U8_Node();
            u8Nodes = new List<U8_Node>();
            stringTable = new List<string>();
            data = new List<byte[]>();

            //Create Rootnode
            fireDebug("   Creating Rootnode...");
            rootNode.Type = U8_NodeType.Directory;
            rootNode.OffsetToName = 0;
            rootNode.OffsetToData = 0;
            rootNode.SizeOfData = (uint)dirEntries.Length + 1;

            //Create Nodes
            for (int i = 0; i < dirEntries.Length; i++)
            {
                fireDebug("   Creating Node #{0} of {1}", i + 1, dirEntries.Length);
                fireProgress((i + 1) * 100 / dirEntries.Length);

                U8_Node tempNode = new U8_Node();
                byte[] tempData = new byte[0];

                string tempDirEntry = dirEntries[i].Remove(0, path.Length - 1);

                if (Directory.Exists(dirEntries[i])) //It's a dir
                {
                    fireDebug("    -> Directory");

                    tempNode.Type = U8_NodeType.Directory;
                    tempNode.OffsetToData = (uint)Shared.CountCharsInString(tempDirEntry, Path.DirectorySeparatorChar); //Recursion

                    int size = u8Nodes.Count + 2;
                    for (int j = 0; j < dirEntries.Length; j++)
                        if (dirEntries[j].Contains(dirEntries[i] + System.IO.Path.DirectorySeparatorChar.ToString())) size++;

                    tempNode.SizeOfData = (uint)size;
                }
                else //It's a file
                {
                    fireDebug("    -> File");
                    fireDebug("    -> Reading File Data...");

                    tempData = File.ReadAllBytes(dirEntries[i]);
                    tempNode.Type = U8_NodeType.File;
                    tempNode.OffsetToData = (uint)offsetToData;
                    tempNode.SizeOfData = (uint)tempData.Length;

                    offsetToData += Shared.AddPadding(offsetToData + tempData.Length, dataPadding);
                }

                tempNode.OffsetToName = (ushort)offsetToName;
                offsetToName += (Path.GetFileName(dirEntries[i])).Length + 1;

                fireDebug("    -> Reading Name...");
                string tempName = Path.GetFileName(dirEntries[i]);

                if (tempName.ToLower() == "icon.bin") iconSize = getRealSize(tempData);
                else if (tempName.ToLower() == "banner.bin") bannerSize = getRealSize(tempData);
                else if (tempName.ToLower() == "sound.bin") soundSize = getRealSize(tempData);

                u8Nodes.Add(tempNode);
                stringTable.Add(tempName);
                data.Add(tempData);
            }

            //Update U8 Header
            fireDebug("   Updating U8 Header...");
            u8Header.HeaderSize = (uint)(((u8Nodes.Count + 1) * 12) + offsetToName);
            u8Header.OffsetToData = (uint)Shared.AddPadding((int)u8Header.OffsetToRootNode + (int)u8Header.HeaderSize, dataPadding);
            
            //Update dataOffsets
            fireDebug("   Calculating Data Offsets...");

            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireDebug("    -> Node #{0} of {1}...", i + 1, u8Nodes.Count);

                int tempOffset = (int)u8Nodes[i].OffsetToData;
                u8Nodes[i].OffsetToData = (uint)(u8Header.OffsetToData + tempOffset);
            }

            fireDebug("Creating U8 File Finished...");
        }
Example #4
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposing && !isDisposed)
            {
                header = null;
                u8Header = null;
                rootNode = null;

                u8Nodes.Clear();
                u8Nodes = null;

                stringTable.Clear();
                stringTable = null;

                data.Clear();
                data = null;
            }

            isDisposed = true;
        }