示例#1
0
        /// <summary>
        /// Checks whether a file is a U8 file or not.
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsU8(byte[] file)
        {
            if (Lz77.IsLz77Compressed(file))
            {
                byte[] partOfFile = new byte[(file.Length > 2000) ? 2000 : file.Length];

                for (int i = 0; i < partOfFile.Length; i++)
                {
                    partOfFile[i] = file[i];
                }

                Lz77 l = new Lz77();
                partOfFile = l.Decompress(partOfFile);

                return(IsU8(partOfFile));
            }
            else
            {
                Headers.HeaderType h = Headers.DetectHeader(file);
                return(Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == 0x55AA382D);
            }
        }
示例#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...");
        }
示例#3
0
        private void writeToStream(Stream writeStream)
        {
            fireDebug("Writing U8 File...");

            //Update Rootnode
            fireDebug("   Updating Rootnode...");
            rootNode.SizeOfData = (uint)u8Nodes.Count + 1;

            MemoryStream u8Stream = new MemoryStream();

            //Write Stringtable
            u8Stream.Seek(u8Header.OffsetToRootNode + ((u8Nodes.Count + 1) * 12), SeekOrigin.Begin);

            fireDebug("   Writing String Table... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            u8Stream.WriteByte(0x00);

            int stringTablePosition = (int)u8Stream.Position - 1;
            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireDebug("    -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count, stringTable[i]);

                u8Nodes[i].OffsetToName = (ushort)(u8Stream.Position - stringTablePosition);
                byte[] stringBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(stringTable[i]);

                u8Stream.Write(stringBytes, 0, stringBytes.Length);
                u8Stream.WriteByte(0x00);
            }

            u8Header.HeaderSize = (uint)(u8Stream.Position - u8Header.OffsetToRootNode);
            u8Header.OffsetToData = 0;

            //Write Data
            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireProgress((i + 1) * 100 / u8Nodes.Count);

                if (u8Nodes[i].Type == U8_NodeType.File)
                {
                    u8Stream.Seek(Shared.AddPadding((int)u8Stream.Position, dataPadding), SeekOrigin.Begin);

                    fireDebug("   Writing Data #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count);

                    if (u8Header.OffsetToData == 0) u8Header.OffsetToData = (uint)u8Stream.Position;
                    u8Nodes[i].OffsetToData = (uint)u8Stream.Position;
                    u8Nodes[i].SizeOfData = (uint)data[i].Length;

                    u8Stream.Write(data[i], 0, data[i].Length);
                }
                else fireDebug("   Node #{0} of {1} is a Directory...", i + 1, u8Nodes.Count);
            }

            //Pad End to 16 bytes
            while (u8Stream.Position % 16 != 0)
                u8Stream.WriteByte(0x00);

            //Write Header + Nodes
            u8Stream.Seek(0, SeekOrigin.Begin);

            fireDebug("   Writing Header... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            u8Header.Write(u8Stream);

            fireDebug("   Writing Rootnode... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            rootNode.Write(u8Stream);

            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireDebug("   Writing Node Entry #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count);
                u8Nodes[i].Write(u8Stream);
            }

            byte[] u8Array = u8Stream.ToArray();
            u8Stream.Dispose();

            if (lz77)
            {
                fireDebug("   Lz77 Compressing U8 File...");

                Lz77 l = new Lz77();
                u8Array = l.Compress(u8Array);
            }

            //Write File Header
            if (headerType == Headers.HeaderType.IMD5)
            {
                fireDebug("   Adding IMD5 Header...");

                writeStream.Seek(0, SeekOrigin.Begin);
                Headers.IMD5 h = Headers.IMD5.Create(u8Array);
                h.Write(writeStream);
            }
            else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET)
            {
                fireDebug("   Adding IMET Header...");

                ((Headers.IMET)header).IconSize = (uint)iconSize;
                ((Headers.IMET)header).BannerSize = (uint)bannerSize;
                ((Headers.IMET)header).SoundSize = (uint)soundSize;

                writeStream.Seek(0, SeekOrigin.Begin);
                ((Headers.IMET)header).Write(writeStream);
            }

            writeStream.Write(u8Array, 0, u8Array.Length);

            fireDebug("Writing U8 File Finished...");
        }
示例#4
0
        /// <summary>
        /// Checks whether a file is a U8 file or not.
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsU8(byte[] file)
        {
            if (Lz77.IsLz77Compressed(file))
            {
                byte[] partOfFile = new byte[(file.Length > 2000) ? 2000 : file.Length];

                for (int i = 0; i < partOfFile.Length; i++)
                    partOfFile[i] = file[i];

                Lz77 l = new Lz77();
                partOfFile = l.Decompress(partOfFile);

                return IsU8(partOfFile);
            }
            else
            {
                Headers.HeaderType h = Headers.DetectHeader(file);
                return (Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == 0x55AA382D);
            }
        }
        private void cbSourceSound_CheckedChanged(object sender, EventArgs e)
        {
            if (cbSourceSound.Checked)
            {
                tbAudioFile.Text = "Internal Sound";

                if (Lz77.IsLz77Compressed(sourceSound))
                { Lz77 l = new Lz77(); sourceSound = l.Decompress(sourceSound); }

                foreach (Label thisLabel in gbWaveInfo.Controls)
                    if (thisLabel.Name.ToLower().Contains("value"))
                    {
                        thisLabel.ForeColor = System.Drawing.Color.Black;
                        thisLabel.Text = "Gathering";
                    }

                bwGatherInfo.RunWorkerAsync(sourceSound);

                //this.Size = new System.Drawing.Size(510, 220);
                this.Size = new System.Drawing.Size(gbWaveInfo.Location.X + gbWaveInfo.Size.Width + 15, this.Size.Height);
            }
            else
            {
                if (tbAudioFile.Text == "Internal Sound")
                    tbAudioFile.Text = string.Empty;

                //this.Size = new System.Drawing.Size(358, 220);
                this.Size = new System.Drawing.Size(btnCancel.Location.X + btnCancel.Size.Width + 15, this.Size.Height);
            }
        }
示例#6
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...");
        }
示例#7
0
        private void writeToStream(Stream writeStream)
        {
            fireDebug("Writing U8 File...");

            //Update Rootnode
            fireDebug("   Updating Rootnode...");
            rootNode.SizeOfData = (uint)u8Nodes.Count + 1;

            MemoryStream u8Stream = new MemoryStream();

            //Write Stringtable
            u8Stream.Seek(u8Header.OffsetToRootNode + ((u8Nodes.Count + 1) * 12), SeekOrigin.Begin);

            fireDebug("   Writing String Table... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            u8Stream.WriteByte(0x00);

            int stringTablePosition = (int)u8Stream.Position - 1;

            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireDebug("    -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count, stringTable[i]);

                u8Nodes[i].OffsetToName = (ushort)(u8Stream.Position - stringTablePosition);
                byte[] stringBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(stringTable[i]);

                u8Stream.Write(stringBytes, 0, stringBytes.Length);
                u8Stream.WriteByte(0x00);
            }

            u8Header.HeaderSize   = (uint)(u8Stream.Position - u8Header.OffsetToRootNode);
            u8Header.OffsetToData = 0;

            //Write Data
            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireProgress((i + 1) * 100 / u8Nodes.Count);

                if (u8Nodes[i].Type == U8_NodeType.File)
                {
                    u8Stream.Seek(Shared.AddPadding((int)u8Stream.Position, dataPadding), SeekOrigin.Begin);

                    fireDebug("   Writing Data #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count);

                    if (u8Header.OffsetToData == 0)
                    {
                        u8Header.OffsetToData = (uint)u8Stream.Position;
                    }
                    u8Nodes[i].OffsetToData = (uint)u8Stream.Position;
                    u8Nodes[i].SizeOfData   = (uint)data[i].Length;

                    u8Stream.Write(data[i], 0, data[i].Length);
                }
                else
                {
                    fireDebug("   Node #{0} of {1} is a Directory...", i + 1, u8Nodes.Count);
                }
            }

            //Pad End to 16 bytes
            while (u8Stream.Position % 16 != 0)
            {
                u8Stream.WriteByte(0x00);
            }

            //Write Header + Nodes
            u8Stream.Seek(0, SeekOrigin.Begin);

            fireDebug("   Writing Header... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            u8Header.Write(u8Stream);

            fireDebug("   Writing Rootnode... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper());
            rootNode.Write(u8Stream);

            for (int i = 0; i < u8Nodes.Count; i++)
            {
                fireDebug("   Writing Node Entry #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count);
                u8Nodes[i].Write(u8Stream);
            }

            byte[] u8Array = u8Stream.ToArray();
            u8Stream.Dispose();

            if (lz77)
            {
                fireDebug("   Lz77 Compressing U8 File...");

                Lz77 l = new Lz77();
                u8Array = l.Compress(u8Array);
            }

            //Write File Header
            if (headerType == Headers.HeaderType.IMD5)
            {
                fireDebug("   Adding IMD5 Header...");

                writeStream.Seek(0, SeekOrigin.Begin);
                Headers.IMD5 h = Headers.IMD5.Create(u8Array);
                h.Write(writeStream);
            }
            else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET)
            {
                fireDebug("   Adding IMET Header...");

                ((Headers.IMET)header).IconSize   = (uint)iconSize;
                ((Headers.IMET)header).BannerSize = (uint)bannerSize;
                ((Headers.IMET)header).SoundSize  = (uint)soundSize;

                writeStream.Seek(0, SeekOrigin.Begin);
                ((Headers.IMET)header).Write(writeStream);
            }

            writeStream.Write(u8Array, 0, u8Array.Length);

            fireDebug("Writing U8 File Finished...");
        }
示例#8
0
        private void writeToStream(Stream writeStream)
        {
            fireDebug("Writing Wad...");

            //Create Footer Timestamp
            if (!keepOriginalFooter)
            {
                fireDebug("   Building Footer Timestamp...");
                createFooterTimestamp();
            }

            //Save Banner App
            if (hasBanner)
            {
                //Compress icon.bin and banner.bin
                if (lz77CompressBannerAndIcon || lz77DecompressBannerAndIcon)
                {
                    for (int i = 0; i < bannerApp.Nodes.Count; i++)
                    {
                        if (bannerApp.StringTable[i].ToLower() == "icon.bin" ||
                            bannerApp.StringTable[i].ToLower() == "banner.bin")
                        {
                            if (!Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77CompressBannerAndIcon)
                            {
                                fireDebug("   Compressing {0}...", bannerApp.StringTable[i]);

                                //Get the data without the IMD5 Header
                                byte[] fileData = new byte[bannerApp.Data[i].Length - 32];
                                Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length);

                                //Compress the data
                                Lz77 l = new Lz77();
                                fileData = l.Compress(fileData);

                                //Add a new IMD5 Header
                                fileData = Headers.IMD5.AddHeader(fileData);
                                bannerApp.Data[i] = fileData;

                                //Update the node
                                bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length;
                            }
                            else if (Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77DecompressBannerAndIcon)
                            {
                                fireDebug("   Decompressing {0}...", bannerApp.StringTable[i]);

                                //Get the data without the IMD5 Header
                                byte[] fileData = new byte[bannerApp.Data[i].Length - 32];
                                Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length);

                                //Decompress the data
                                Lz77 l = new Lz77();
                                fileData = l.Decompress(fileData);

                                //Add a new IMD5 Header
                                fileData = Headers.IMD5.AddHeader(fileData);
                                bannerApp.Data[i] = fileData;

                                //Update the node
                                bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length;
                            }
                        }
                    }
                }

                for (int i = 0; i < contents.Count; i++)
                    if (tmd.Contents[i].Index == 0x0000)
                    { fireDebug("   Saving Banner App..."); contents[i] = bannerApp.ToByteArray(); break; }
            }

            //Update Header (Content Size)
            fireDebug("   Updating Header...");
            int contentSize = 0;
            for (int i = 0; i < contents.Count - 1; i++)
                contentSize += Shared.AddPadding(contents[i].Length);

            contentSize += contents[contents.Count - 1].Length;

            wadHeader.ContentSize = (uint)contentSize;
            wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36);

            //Update Contents
            fireDebug("   Updating TMD Contents...");
            tmd.UpdateContents(contents.ToArray());

            //Write Header
            fireDebug("   Writing Wad Header... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper());
            writeStream.Seek(0, SeekOrigin.Begin);
            wadHeader.Write(writeStream);

            //Write Cert
            fireDebug("   Writing Certificate Chain... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper());
            writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin);
            byte[] temp = cert.ToByteArray();
            writeStream.Write(temp, 0, temp.Length);

            //Write Tik
            fireDebug("   Writing Ticket... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper());
            writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin);
            temp = tik.ToByteArray();
            writeStream.Write(temp, 0, temp.Length);

            //Write TMD
            fireDebug("   Writing TMD... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper());
            writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin);
            temp = tmd.ToByteArray();
            writeStream.Write(temp, 0, temp.Length);

            //Write Contents
            ContentIndices[] contentList = tmd.GetSortedContentList();

            for (int i = 0; i < contentList.Length; i++)
            {
                writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin);

                fireProgress((i + 1) * 100 / contents.Count);

                fireDebug("   Writing Content #{1} of {2}... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper(), i + 1, contents.Count);
                fireDebug("    -> Content ID: 0x{0}", tmd.Contents[contentList[i].Index].ContentID.ToString("x8"));
                fireDebug("    -> Index: 0x{0}", tmd.Contents[contentList[i].Index].Index.ToString("x4"));
                fireDebug("    -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[contentList[i].Index].Type).ToString("x4"), tmd.Contents[contentList[i].Index].Type.ToString());
                fireDebug("    -> Size: {0} bytes", tmd.Contents[contentList[i].Index].Size);
                fireDebug("    -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[contentList[i].Index].Hash));

                temp = encryptContent(contents[contentList[i].Index], contentList[i].Index);
                writeStream.Write(temp, 0, temp.Length);
            }

            //Write Footer
            if (wadHeader.FooterSize > 0)
            {
                fireDebug("   Writing Footer... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper());
                writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin);
                writeStream.Write(footer, 0, footer.Length);
            }

            //Padding
            while (writeStream.Position % 64 != 0)
                writeStream.WriteByte(0x00);

            fireDebug("Writing Wad Finished... (Written Bytes: {0})", writeStream.Position);
        }
示例#9
0
        private void cmOptionsExtract_MouseClick(object sender, EventArgs e)
        {
            ToolStripMenuItem cmSender = sender as ToolStripMenuItem;

            if (cmSender.OwnerItem == tsExtractImages)
            {
                try
                {
                    FolderBrowserDialog fbd = new FolderBrowserDialog();

                    if (cmSender.Text.ToLower() == "both") { fbd.Description = "Select the path where the images will be extracted to. Two folders \"Banner\" and \"Icon\" will be created."; }
                    else { fbd.Description = "Select the path where the images will be extracted to."; }

                    if (fbd.ShowDialog() == DialogResult.OK)
                    {
                        string bannerPath;
                        string iconPath;

                        switch (cmSender.Text.ToLower())
                        {
                            case "banner":
                                bannerPath = fbd.SelectedPath;
                                iconPath = string.Empty;
                                break;
                            case "icon":
                                bannerPath = string.Empty;
                                iconPath = fbd.SelectedPath;
                                break;
                            default: //both
                                bannerPath = fbd.SelectedPath + Path.DirectorySeparatorChar + "Banner";
                                iconPath = fbd.SelectedPath + Path.DirectorySeparatorChar + "Icon";
                                break;
                        }

                        if (!string.IsNullOrEmpty(bannerPath))
                        {
                            if (!Directory.Exists(bannerPath)) Directory.CreateDirectory(bannerPath);

                            if (string.IsNullOrEmpty(replacedBanner))
                            {
                                for (int i = 0; i < bannerBin.NumOfNodes; i++)
                                {
                                    if (bannerBin.StringTable[i].ToLower().EndsWith(".tpl"))
                                    {
                                        Image img = TPL.Load(bannerBin.Data[i]).ExtractTexture();
                                        img.Save(bannerPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(bannerBin.StringTable[i]) + ".png");
                                    }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newBannerBin.NumOfNodes; i++)
                                {
                                    if (newBannerBin.StringTable[i].ToLower().EndsWith(".tpl"))
                                    {
                                        Image img = TPL.Load(newBannerBin.Data[i]).ExtractTexture();
                                        img.Save(bannerPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(newBannerBin.StringTable[i]) + ".png");
                                    }
                                }
                            }
                        }

                        if (!string.IsNullOrEmpty(iconPath))
                        {
                            if (!Directory.Exists(iconPath)) Directory.CreateDirectory(iconPath);

                            if (string.IsNullOrEmpty(replacedIcon))
                            {
                                for (int i = 0; i < iconBin.NumOfNodes; i++)
                                {
                                    if (iconBin.StringTable[i].ToLower().EndsWith(".tpl"))
                                    {
                                        Image img = TPL.Load(iconBin.Data[i]).ExtractTexture();
                                        img.Save(iconPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(iconBin.StringTable[i]) + ".png");
                                    }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newIconBin.NumOfNodes; i++)
                                {
                                    if (newIconBin.StringTable[i].ToLower().EndsWith(".tpl"))
                                    {
                                        Image img = TPL.Load(newIconBin.Data[i]).ExtractTexture();
                                        img.Save(iconPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(newIconBin.StringTable[i]) + ".png");
                                    }
                                }
                            }
                        }

                        infoBox("Extracted images successfully!");
                    }
                }
                catch (Exception ex) { errorBox(ex.Message); }
            }
            else if (cmSender.OwnerItem == tsExtractSound)
            {
                try
                {
                    byte[] soundFile = new byte[0];

                    if (string.IsNullOrEmpty(replacedSound))
                    {
                        for (int i = 0; i < sourceWad.BannerApp.NumOfNodes; i++)
                        {
                            if (sourceWad.BannerApp.StringTable[i].ToLower() == "sound.bin")
                                soundFile = sourceWad.BannerApp.Data[i];
                        }
                    }
                    else
                    { soundFile = newSoundBin; }

                    SaveFileDialog sfd = new SaveFileDialog();
                    if (cmSender.Name.ToLower() == "cmextractsoundasbin") { sfd.Filter = "BIN|*.bin"; sfd.FileName = "sound.bin"; }
                    else if (cmSender.Name.ToLower() == "cmextractsoundasaudio")
                    {
                        if (soundFile[32] == 'R' && soundFile[33] == 'I' && soundFile[34] == 'F' && soundFile[35] == 'F')
                        { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; }
                        else if (soundFile[32] == 'B' && soundFile[33] == 'N' && soundFile[34] == 'S' && soundFile[35] == ' ')
                        { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; }
                        else if (soundFile[32] == 'F' && soundFile[33] == 'O' && soundFile[34] == 'R' && soundFile[35] == 'M')
                        { sfd.Filter = "AIFF|*.aif;*.aiff"; sfd.FileName = "sound.aif"; }
                        else if (soundFile[32] == 'L' && soundFile[33] == 'Z' && soundFile[34] == '7' && soundFile[35] == '7')
                        {
                            if (soundFile[41] == 'R' && soundFile[42] == 'I' && soundFile[43] == 'F' && soundFile[44] == 'F')
                            { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; }
                            else if (soundFile[41] == 'B' && soundFile[42] == 'N' && soundFile[43] == 'S' && soundFile[44] == ' ')
                            { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wave"; }
                            else if (soundFile[41] == 'F' && soundFile[42] == 'O' && soundFile[43] == 'R' && soundFile[44] == 'M')
                            { sfd.Filter = "AIFF|*.aif;*.aiff"; sfd.FileName = "sound.aif"; }
                            else throw new Exception("Unsupported Audio Format!");
                        }
                        else throw new Exception("Unsupported Audio Format!");
                    }

                    if (sfd.ShowDialog() == DialogResult.OK)
                    {
                        if (File.Exists(sfd.FileName)) File.Delete(sfd.FileName);

                        if (sfd.FileName.ToLower().EndsWith(".bin"))
                        {
                            File.WriteAllBytes(sfd.FileName, soundFile);
                            infoBox("The sound.bin was successfully extraced!");
                        }
                        else
                        {
                            soundFile = Headers.IMD5.RemoveHeader(soundFile);

                            if (Lz77.IsLz77Compressed(soundFile))
                            { Lz77 l = new Lz77(); soundFile = l.Decompress(soundFile); }

                            if (soundFile[0] == 'B' && soundFile[1] == 'N' && soundFile[2] == 'S' && soundFile[3] == ' ')
                            {
                                Wave w = BNS.BnsToWave(soundFile);
                                w.Save(sfd.FileName);
                                w.Dispose();
                            }
                            else
                                File.WriteAllBytes(sfd.FileName, soundFile);

                            infoBox(string.Format("The sound.bin was successfully converted to {0}!", Path.GetFileName(sfd.FileName)));
                        }
                    }
                }
                catch (Exception ex) { errorBox(ex.Message); }
            }
            else if (cmSender.OwnerItem == tsExtractBrl)
            {
                try
                {
                    FolderBrowserDialog fbd = new FolderBrowserDialog();
                    fbd.Description = "Select the path where the files will be extracted to.";

                    if (fbd.ShowDialog() == DialogResult.OK)
                    {
                        if (cmSender == cmExtractBrlyt || cmSender == cmExtractBothBrl)
                        {
                            //Extract brlyts
                            if (string.IsNullOrEmpty(replacedBanner))
                            {
                                for (int i = 0; i < bannerBin.NumOfNodes; i++)
                                {
                                    if (bannerBin.StringTable[i].ToLower().EndsWith(".brlyt"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + bannerBin.StringTable[i], bannerBin.Data[i]); }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newBannerBin.NumOfNodes; i++)
                                {
                                    if (newBannerBin.StringTable[i].ToLower().EndsWith(".brlyt"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newBannerBin.StringTable[i], newBannerBin.Data[i]); }
                                }
                            }

                            if (string.IsNullOrEmpty(replacedIcon))
                            {
                                for (int i = 0; i < iconBin.NumOfNodes; i++)
                                {
                                    if (iconBin.StringTable[i].ToLower().EndsWith(".brlyt"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + iconBin.StringTable[i], iconBin.Data[i]); }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newIconBin.NumOfNodes; i++)
                                {
                                    if (newIconBin.StringTable[i].ToLower().EndsWith(".brlyt"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newIconBin.StringTable[i], newIconBin.Data[i]); }
                                }
                            }
                        }

                        if (cmSender == cmExtractBothBrl || cmSender == cmExtractBrlan)
                        {
                            //Extract brlans
                            if (string.IsNullOrEmpty(replacedBanner))
                            {
                                for (int i = 0; i < bannerBin.NumOfNodes; i++)
                                {
                                    if (bannerBin.StringTable[i].ToLower().EndsWith(".brlan"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + bannerBin.StringTable[i], bannerBin.Data[i]); }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newBannerBin.NumOfNodes; i++)
                                {
                                    if (newBannerBin.StringTable[i].ToLower().EndsWith(".brlan"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newBannerBin.StringTable[i], newBannerBin.Data[i]); }
                                }
                            }

                            if (string.IsNullOrEmpty(replacedIcon))
                            {
                                for (int i = 0; i < iconBin.NumOfNodes; i++)
                                {
                                    if (iconBin.StringTable[i].ToLower().EndsWith(".brlan"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + iconBin.StringTable[i], iconBin.Data[i]); }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < newIconBin.NumOfNodes; i++)
                                {
                                    if (newIconBin.StringTable[i].ToLower().EndsWith(".brlan"))
                                    { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newIconBin.StringTable[i], newIconBin.Data[i]); }
                                }
                            }
                        }

                        infoBox("Extracted files successfully!");
                    }
                }
                catch (Exception ex) { errorBox(ex.Message); }
            }
            else //DOL
            {
                try
                {
                    if (sourceWad.NumOfContents == 3)
                    {
                        int appIndex = 0;
                        if (sourceWad.BootIndex == 1) appIndex = 2;
                        else if (sourceWad.BootIndex == 2) appIndex = 1;

                        if (appIndex > 0)
                        {
                            SaveFileDialog sfd = new SaveFileDialog();
                            sfd.Filter = "Wii Executables|*.dol"; sfd.FileName = (string.IsNullOrEmpty(tbAllLanguages.Text) ? tbEnglish.Text : tbAllLanguages.Text) + ".dol";

                            if (sfd.ShowDialog() == DialogResult.OK)
                            {
                                if (File.Exists(sfd.FileName)) File.Delete(sfd.FileName);
                                File.WriteAllBytes(sfd.FileName, sourceWad.Contents[appIndex]);
                                infoBox(string.Format("The DOL file was successfully extracted to {0}!", Path.GetFileName(sfd.FileName)));
                            }
                        }
                        else errorBox("The DOL file couldn't be found!");
                    }
                    else errorBox("The DOL file couldn't be found!");
                }
                catch (Exception ex) { errorBox(ex.Message); }
            }
        }
示例#10
0
        private Stream compress(Stream inFile)
        {
            if (Lz77.IsLz77Compressed(inFile))
            {
                return(inFile);
            }
            inFile.Seek(0, SeekOrigin.Begin);

            int textSize = 0;
            int codeSize = 0;

            int i, c, r, s, length, lastMatchLength, codeBufferPointer, mask;

            int[] codeBuffer = new int[17];

            uint         fileSize = ((Convert.ToUInt32(inFile.Length)) << 8) + 0x10;
            MemoryStream outFile  = new MemoryStream();

            outFile.Write(BitConverter.GetBytes(Shared.Swap(lz77Magic)), 0, 4);
            outFile.Write(BitConverter.GetBytes(fileSize), 0, 4);

            InitTree();
            codeBuffer[0]     = 0;
            codeBufferPointer = 1;
            mask = 0x80;
            s    = 0;
            r    = N - F;

            for (i = s; i < r; i++)
            {
                textBuffer[i] = 0xffff;
            }

            for (length = 0; length < F && (c = (int)inFile.ReadByte()) != -1; length++)
            {
                textBuffer[r + length] = (ushort)c;
            }

            if ((textSize = length) == 0)
            {
                return(inFile);
            }

            for (i = 1; i <= F; i++)
            {
                InsertNode(r - i);
            }
            InsertNode(r);

            do
            {
                if (matchLength > length)
                {
                    matchLength = length;
                }

                if (matchLength <= threshold)
                {
                    matchLength = 1;
                    codeBuffer[codeBufferPointer++] = textBuffer[r];
                }
                else
                {
                    codeBuffer[0] |= mask;

                    codeBuffer[codeBufferPointer++] = (char)
                                                      (((r - matchPosition - 1) >> 8) & 0x0f) |
                                                      ((matchLength - (threshold + 1)) << 4);

                    codeBuffer[codeBufferPointer++] = (char)((r - matchPosition - 1) & 0xff);
                }

                if ((mask >>= 1) == 0)
                {
                    for (i = 0; i < codeBufferPointer; i++)
                    {
                        outFile.WriteByte((byte)codeBuffer[i]);
                    }

                    codeSize     += codeBufferPointer;
                    codeBuffer[0] = 0; codeBufferPointer = 1;
                    mask          = 0x80;
                }

                lastMatchLength = matchLength;
                for (i = 0; i < lastMatchLength && (c = (int)inFile.ReadByte()) != -1; i++)
                {
                    DeleteNode(s);

                    textBuffer[s] = (ushort)c;
                    if (s < F - 1)
                    {
                        textBuffer[s + N] = (ushort)c;
                    }
                    s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);

                    InsertNode(r);
                }

                while (i++ < lastMatchLength)
                {
                    DeleteNode(s);

                    s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
                    if (--length != 0)
                    {
                        InsertNode(r);
                    }
                }
            } while (length > 0);


            if (codeBufferPointer > 1)
            {
                for (i = 0; i < codeBufferPointer; i++)
                {
                    outFile.WriteByte((byte)codeBuffer[i]);
                }
                codeSize += codeBufferPointer;
            }

            if (codeSize % 4 != 0)
            {
                for (i = 0; i < 4 - (codeSize % 4); i++)
                {
                    outFile.WriteByte(0x00);
                }
            }

            return(outFile);
        }
示例#11
0
        private Stream decompress(Stream inFile)
        {
            if (!Lz77.IsLz77Compressed(inFile))
            {
                return(inFile);
            }
            inFile.Seek(0, SeekOrigin.Begin);

            int  i, j, k, r, c, z;
            uint flags, decompressedSize, currentSize = 0;

            Headers.HeaderType h = Headers.DetectHeader(inFile);

            byte[] temp = new byte[8];
            inFile.Seek((int)h, SeekOrigin.Begin);
            inFile.Read(temp, 0, 8);

            if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != lz77Magic)
            {
                inFile.Dispose(); throw new Exception("Invaild Magic!");
            }
            if (temp[4] != 0x10)
            {
                inFile.Dispose(); throw new Exception("Unsupported Compression Type!");
            }

            decompressedSize = (BitConverter.ToUInt32(temp, 4)) >> 8;

            for (i = 0; i < N - F; i++)
            {
                textBuffer[i] = 0xdf;
            }
            r = N - F; flags = 7; z = 7;

            MemoryStream outFile = new MemoryStream();

            while (true)
            {
                flags <<= 1;
                z++;

                if (z == 8)
                {
                    if ((c = inFile.ReadByte()) == -1)
                    {
                        break;
                    }

                    flags = (uint)c;
                    z     = 0;
                }

                if ((flags & 0x80) == 0)
                {
                    if ((c = inFile.ReadByte()) == inFile.Length - 1)
                    {
                        break;
                    }
                    if (currentSize < decompressedSize)
                    {
                        outFile.WriteByte((byte)c);
                    }

                    textBuffer[r++] = (byte)c;
                    r &= (N - 1);
                    currentSize++;
                }
                else
                {
                    if ((i = inFile.ReadByte()) == -1)
                    {
                        break;
                    }
                    if ((j = inFile.ReadByte()) == -1)
                    {
                        break;
                    }

                    j = j | ((i << 8) & 0xf00);
                    i = ((i >> 4) & 0x0f) + threshold;
                    for (k = 0; k <= i; k++)
                    {
                        c = textBuffer[(r - j - 1) & (N - 1)];
                        if (currentSize < decompressedSize)
                        {
                            outFile.WriteByte((byte)c);
                        }
                        textBuffer[r++] = (byte)c; r &= (N - 1); currentSize++;
                    }
                }
            }

            return(outFile);
        }