Пример #1
0
        static void Main(string[] args)
        {
            Console.Write("PAPA_Tool\nProgrammed by GovanifY for ChrisX930\n\n1) Extract 2) Create\n");
            string choice = Console.ReadLine();
            if (choice == "1")
            {
                Console.WriteLine("\n\nPlease enter the name of the file to extract: ");
                string arg = Console.ReadLine();
                if (File.Exists(arg))
                {

                    BinaryStream input = new BinaryStream(File.Open(arg, FileMode.Open));
                    UInt32 magic = input.ReadUInt32();
                    if (magic != 0x41504150) { Console.WriteLine("INCORRECT MAGIC!\nExiting..."); return; }
                    input.ReadUInt32();//Padding
                    UInt32 Headeroffset = input.ReadUInt32();
                    UInt32 Headersize = input.ReadUInt32();
                    UInt32 count = input.ReadUInt32();
                    count -= 1;
                    string dirname = "@" + arg + "/";
                    #region Dir creation
                    try
                    {
                        Directory.CreateDirectory(dirname);
                    }
                    catch (IOException e)
                    {
                        Console.Write("Failed creating directory: {0}", e.Message);
                    }
                    #endregion
                    for (int i = 0; i < count; i++)
                    {
                        UInt32 FileOffset = input.ReadUInt32();
                        long tmp = input.Tell();
                        UInt32 NextFileOffset = input.ReadUInt32();
                        UInt32 FileSize = NextFileOffset;
                        FileSize -= FileOffset + 5*4;

                        input.Seek(FileOffset, SeekOrigin.Begin);
                        Console.WriteLine("Extracting...: {0}", "@" + arg + "/" + i + ".bin");
                        UInt32 completesize = input.ReadUInt32();
                        input.ReadUInt32();
                        input.ReadUInt32();
                        input.ReadUInt32();//Constants: 3 then 14 then 18
                        UInt32 secondsize = input.ReadUInt32();
                        byte[] PAPAtmp = input.ReadBytes((int)FileSize);
                        var PAPAfs = new FileStream("@" + arg + "/" + i + ".bin", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
                        PAPAfs.Write(PAPAtmp, 0, PAPAtmp.Length);
                        input.Seek(tmp, SeekOrigin.Begin);

                    }
                }
                else
                {
                    Console.WriteLine("Cannot open file!");
                }
            }
            else
            {
                if (choice == "2")
                {
                    long disposer;
                    Console.WriteLine("\n\nPlease enter the name of the file to create: ");
                    string arg = Console.ReadLine();
                    BinaryWriter output = new BinaryWriter(File.Open(Path.GetFileNameWithoutExtension(arg) + "Modded" + Path.GetExtension(arg), FileMode.Create));
                    string dirname = "@" + arg + "/";
                    output.Write((UInt32)0x41504150);//Magic!
                    output.Write((UInt32)0);//Padding

                    output.Write((UInt32)0xC);
                    output.Write((UInt32)0xADC);//Header offset and size, but always constants!

                    string[] files = Directory.GetFiles(dirname);//The files are sorted numerically by default, all hail to .NET o/(actually not)
                    NumericComparer ns = new NumericComparer();
                    Array.Sort(files, ns);
                    output.Write((UInt32)files.Length + 1);//Number of files
                    for (int i = 0; i < files.Length; i++ )
                    {
                        output.Write((UInt32)0);//FileOffset
                        //Garbages since we're going to mod this later
                    }
                    disposer = output.BaseStream.Position;
                    int y = 0;
                    foreach (string name in files)
                    {
                        byte[] file = File.ReadAllBytes(name);
                        output.Write((UInt32)file.Length + 5 * 4);//Complete Size

                        output.Write((UInt32)0x3);//Constants
                        output.Write((UInt32)0x14);//Constants
                        output.Write((UInt32)0x18);//Constants

                        output.Write((UInt32)file.Length + 4);//Second Size

                        output.Write(file);
                        //Then write file datas here
                        long tmp = output.BaseStream.Position;

                        output.Seek(20 + y * 4, SeekOrigin.Begin);
                        output.Write((UInt32)disposer);

                        output.Seek((int)tmp, SeekOrigin.Begin);
                        disposer = output.BaseStream.Position;
                        y++;
                    }

                }
                else
                {
                    Console.WriteLine("Please enter a correct option!");
                }
            }
        }
Пример #2
0
        static void Main(string[] args)
        {
            Console.Write("XBB_Tool\nProgrammed by GovanifY for ChrisX930\n\n1) Extract 2) Create\n");
            string choice = Console.ReadLine();
            if (choice == "1")
            {
                Console.WriteLine("\n\nPlease enter the name of the file to extract: ");
                string arg = Console.ReadLine();
            if (File.Exists(arg))
            {

                BinaryStream input = new BinaryStream(File.Open(arg, FileMode.Open));
                UInt32 magic = input.ReadUInt32();
                if (magic != 0x01424258) { Console.WriteLine("INCORRECT MAGIC!\nExiting..."); return; }
                UInt32 count = input.ReadUInt32();
                input.Seek(0x20, SeekOrigin.Begin);//Padding...?
                string dirname = "@" + arg + "/";
                #region Dir creation
                try
                {
                    Directory.CreateDirectory(dirname);
                }
                catch (IOException e)
                {
                    Console.Write("Failed creating directory: {0}", e.Message);
                }
                #endregion
                for (int i = 0; i < count; i++)
                {
                    UInt32 offset = input.ReadUInt32();
                    UInt32 size = input.ReadUInt32();
                    UInt32 nameoffset = input.ReadUInt32();
                    UInt32 ID = input.ReadUInt32();

                    long tmp = input.Tell();
                    input.Seek(nameoffset, SeekOrigin.Begin);
                    byte[] namet = new byte[0];
                    //Reads name until 0
                    while(true)
                    {
                        byte test = input.ReadByte();
                        if (test == 0){goto next;}
                        byte[] tmpnamet = new byte[namet.Length + 1];
                        namet.CopyTo(tmpnamet, 1);
                        tmpnamet[0] = test;
                        namet = tmpnamet;
                    }
                next:
                    Array.Reverse(namet, 0, namet.Length);
                  string name = dirname + Encoding.ASCII.GetString(namet);
                Console.WriteLine("Extracting...: {0}", name);
                    input.Seek(offset, SeekOrigin.Begin);

            byte[] PAPAtmp = input.ReadBytes((int)size);
            var PAPAfs = new FileStream(name, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
            PAPAfs.Write(PAPAtmp, 0, PAPAtmp.Length);
            input.Seek(tmp, SeekOrigin.Begin);

                }
            }
            else
            {
                Console.WriteLine("Cannot open file!");
            }
            }
            else
            {
                if (choice == "2")
                {
                    Console.WriteLine("\n\nPlease enter the name of the file to create: ");
                    string arg = Console.ReadLine();
                    BinaryWriter output = new BinaryWriter(File.Open(Path.GetFileNameWithoutExtension(arg) + "Modded" + Path.GetExtension(arg), FileMode.Create));
                   string dirname = "@" + arg + "/";
                        UInt32 IDCustom = 0x90000000;
                        output.Write((uint)0x01424258);
                        string[] files = Directory.GetFiles(dirname);
                        output.Write((uint)files.Length);
                        output.Write((uint)0);//Padding
                        output.Write((uint)0);//Padding
                        output.Write((uint)0);//Padding
                        output.Write((uint)0);//Padding
                        output.Write((uint)0);//Padding
                        output.Write((uint)0);//Padding
                        BinaryStream input = new BinaryStream(File.Open(arg, FileMode.Open));
                        UInt32 magic = input.ReadUInt32();
                        if (magic != 0x01424258) { Console.WriteLine("INCORRECT MAGIC!\nExiting..."); return; }
                        UInt32 count = input.ReadUInt32();
                        input.Seek(0x20, SeekOrigin.Begin);//Padding...?
                        int disposername = (files.Length * 4 * 4) + 0x20 + 8 + (files.Length * 4 * 2);
                        int disposer2LBA = (files.Length * 4 * 4) + 0x20 + 8;
                        /*long tmp = output.BaseStream.Position;
                        output.Seek(disposername - 8, SeekOrigin.Begin);
                        output.Write((UInt32)0);//Garbage, dunno what those 2 bytes are
                        output.Write((UInt32)0);
                        output.Seek((int)tmp, SeekOrigin.Begin);*/
                        int disposer = (files.Length * 4 * 4) + 0x20 + 8 + 2 + (files.Length * 4 * 2);
                        foreach (string name in files)
                        {
                            disposer += Path.GetFileName(name).Length + 1;
                        }
                        foreach (string name in files)
                        {
                            UInt32 ID;
                            UInt32 unk1;
                            UInt32 unk2;
                            try
                            {
                            input.ReadUInt32();
                            input.ReadUInt32();
                            input.ReadUInt32();
                            ID = input.ReadUInt32();
                            long tmp = input.Tell();
                            input.Seek(disposer2LBA, SeekOrigin.Begin);
                            unk1 = input.ReadUInt32();
                            unk2 = input.ReadUInt32();
                            input.Seek(tmp, SeekOrigin.Begin);
                            }
                            catch
                            {
                               unk1 = 0;
                               unk2 = 0;
                               ID = IDCustom;//custom ID
                            }
                            byte[] file = File.ReadAllBytes(name);
                            output.Write((UInt32)disposer);
                            output.Write((UInt32)file.Length);//Size
                            output.Write((UInt32)disposername);
                            output.Write((UInt32)ID);
                            Console.WriteLine("Adding: {0}, using ID {1}",name, ID);
                            IDCustom++;
                            long tmp2 = output.BaseStream.Position;
                            output.Seek(disposer2LBA, SeekOrigin.Begin);
                            output.Write(unk1);
                            output.Write(unk2);//Unknowns to figure out!!!
                            disposer2LBA += 8;
                            output.Seek(disposername, SeekOrigin.Begin);
                            disposername += Path.GetFileName(name).Length + 1;
                            byte[] tmp3 = System.Text.Encoding.ASCII.GetBytes(Path.GetFileName(name));
                            byte[] tmp4 = new byte[] { 0x00 };
                            output.Write(tmp3);
                            output.Write(tmp4);
                            output.Seek(disposer, SeekOrigin.Begin);
                            output.Write(file);
                            disposer += file.Length;
                            output.Seek((int)tmp2, SeekOrigin.Begin);
                        }
                }
                else
                {
                    Console.WriteLine("Please enter a correct option!");
                }
            }
        }
Пример #3
0
        private static void KH2PatchExtractor(Stream patch, string outputname)
        {
            try
            {
            Directory.CreateDirectory(Path.GetDirectoryName("output/"));
            }
            catch
            {
            } //Creating folder
            using (var br = new BinaryStream(patch, Encoding.ASCII, leaveOpen: true))
            {
            using (TextWriter op = new StreamWriter("output/log.log"))
            {
            uint tmp = br.ReadUInt32();
            if (tmp != 1345472587u && tmp != 1362249803u)
            {
            br.Close();
            br.Close();
            throw new InvalidDataException("Invalid KH2Patch file!");
            }
            uint oaAuther = br.ReadUInt32(),
            obFileCount = br.ReadUInt32(),
            num = br.ReadUInt32();
            string patchname = "";
            patchname = Path.GetFileName(patchname);
            try
            {
            string author = br.ReadCString();
            op.WriteLine(author);
            op.WriteLine(num);
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Loading patch {0} version {1} by {2}", patchname, num, author);
            Console.ResetColor();
            br.Seek(oaAuther, SeekOrigin.Begin);
            uint os1 = br.ReadUInt32(),
            os2 = br.ReadUInt32(),
            os3 = br.ReadUInt32();
            br.Seek(oaAuther + os1, SeekOrigin.Begin);
            num = br.ReadUInt32();
            if (num > 0)
            {
            br.Seek(num * 4, SeekOrigin.Current);
            //Console.WriteLine("Changelog:");
            Console.ForegroundColor = ConsoleColor.Green;
            while (num > 0)
            {
            --num;
            op.WriteLine(br.ReadCString());
            //Console.WriteLine(" * {0}", br.ReadCString());
            }
            op.WriteLine("");
            }
            br.Seek(oaAuther + os2, SeekOrigin.Begin);
            num = br.ReadUInt32();
            if (num > 0)
            {
            br.Seek(num * 4, SeekOrigin.Current);
            Console.ResetColor();
            //Console.WriteLine("Credits:");
            Console.ForegroundColor = ConsoleColor.Green;
            while (num > 0)
            {
            --num;
            op.WriteLine(br.ReadCString());
            //Console.WriteLine(" * {0}", br.ReadCString());
            }
            op.WriteLine("");
            Console.ResetColor();
            }
            br.Seek(oaAuther + os3, SeekOrigin.Begin);
            author = br.ReadCString();
            /*author = author.Replace("\r\n", string.Empty);
            author = author.Replace("\n", string.Empty);//Shitty but I know someone who made mods for adding more than one line...*/
            if (author.Length != 0)
            {
            // Console.WriteLine("Other information:\r\n");
            Console.ForegroundColor = ConsoleColor.Green;
            op.WriteLine(author);
            //Console.WriteLine("{0}", author);
            }
            op.WriteLine("");
            Console.ResetColor();
            }
            catch (Exception e)
            {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Error reading kh2patch header: {0}: {1}\r\nAttempting to continue files...",
            e.GetType(), e.Message);
            Console.ResetColor();
            }
            Console.WriteLine("");
            br.Seek(obFileCount, SeekOrigin.Begin);
            num = br.ReadUInt32();
            while (num > 0)
            {
            --num;
            uint Hash = br.ReadUInt32();
            oaAuther = br.ReadUInt32();
            uint CompressedSize = br.ReadUInt32();
            uint UncompressedSize = br.ReadUInt32();
            uint Parent = br.ReadUInt32();
            uint Relink = br.ReadUInt32();
            bool Compressed = br.ReadUInt32() != 0;
            bool IsNew = br.ReadUInt32() == 1; //Custom

            string fname3 = "";

            string fname2;
            if (Relink == 0)
            {
            if (CompressedSize != 0)
            {
            var KH2PFileStream = new Substream(patch, oaAuther, CompressedSize);
            if (HashList.HashList.pairs.TryGetValue(Hash, out fname2)) { Console.Write("Extracting {0}...", fname2); }
            else
            { fname2 = String.Format("@noname/{0:X8}.bin", Hash); ; Console.Write("Extracting {0}...", fname2); }
            long brpos = br.Tell();
            KH2PATCHInternal(KH2PFileStream, fname2, Compressed, UncompressedSize);
            br.ChangePosition((int)brpos);
            //Changing the original position of the BinaryReader for what's next
            }
            else
            {
            throw new InvalidDataException("File length is 0, but not relinking.");
            }

            op.WriteLine(fname2);
            op.WriteLine(fname3);
            string Compressed2 = "";
            if (Compressed) { Compressed2 = "y"; } else { Compressed2 = "n"; }
            op.WriteLine(Compressed2);
            string Parent2 = "";
            if (Parent == 0) { }
            if (Parent == 1) { Parent2 = "OVL"; }
            if (Parent == 2) { Parent2 = "ISO"; }
            op.WriteLine(Parent2);
            string IsNew2 = "";
            if (IsNew) { IsNew2 = "y"; } else { IsNew2 = "n"; }
            op.WriteLine(IsNew2);
            }
            else
            {
            if (!HashList.HashList.pairs.TryGetValue(Hash, out fname2)) { fname2 = String.Format("@noname/{0:X8}.bin", Hash); }
            if (!HashList.HashList.pairs.TryGetValue(Relink, out fname3))
            {
            fname3 = String.Format("@noname/{0:X8}.bin", Relink);
            }
            Console.WriteLine("File {1} relinked to {0}, no need to extract", fname3, fname2);

            op.WriteLine(fname2);
            op.WriteLine(fname3);
            string Parent2 = "";
            if (Parent == 0) { }
            if (Parent == 1) { Parent2 = "OVL"; }
            if (Parent == 2) { Parent2 = "ISO"; }
            op.WriteLine(Parent2);
            string IsNew2 = "";
            if (IsNew) { IsNew2 = "y"; } else { IsNew2 = "n"; }
            op.WriteLine(IsNew2);
            }

            br.Seek(60, SeekOrigin.Current);
            }
            op.WriteLine("");
            using (TextWriter bat = new StreamWriter("output/output.bat"))
            {
            bat.WriteLine("@echo off");
            bat.WriteLine("KH2FM_Toolkit.exe -patchmaker -batch -uselog log.log -output \"{0}\"", outputname);
            }
            File.Copy(System.Reflection.Assembly.GetEntryAssembly().Location, "output/KH2FM_Toolkit.exe");
            }
            } //End of br
        }
Пример #4
0
        private static void CreateFireEmblemArchive(string outdir, string newname)
        {
            Console.WriteLine("Creating archive {0}", Path.GetFileName(newname));
            FileStream newfilestream = File.Create(newname);
            //Let's get the number of files
            string[] files = Directory.GetFiles(outdir);

            uint FileCount = (uint)files.Length;
            Console.WriteLine("{0} files detected!", FileCount);

            var ShiftJIS = Encoding.GetEncoding(932);

            BinaryStream newFile = new BinaryStream(newfilestream);

            MemoryStream infos = new MemoryStream();
            BinaryWriter FileInfos = new BinaryWriter(infos);

            Console.WriteLine("Creating dummy header...");
            newFile.Write(0);//Dummy; file size

            //MetaOffset 0x4
            newFile.Write(0);//dummy should be MetaOffset
            newFile.Write(FileCount);
            newFile.Write(FileCount + 3);

            byte nil = 0;
            for (int i = 0; i < 0x70; i++)
            {
                newFile.Write(nil);
            }
            int z = 0;
            foreach (string fileName in files)
            {
                Console.WriteLine("Adding file {0}...", Path.GetFileName(fileName));
                byte[] filetoadd = File.ReadAllBytes(fileName);
                uint fileoff = (uint)newFile.Tell();
                newFile.Write(filetoadd);
                while ((int)newFile.Tell() % 128 != 0)
                {
                    newFile.Write(nil);
                }
                FileInfos.Write(0);//Name position
                FileInfos.Write(z);//FileIndex
                FileInfos.Write(filetoadd.Length);//Length of the file
                FileInfos.Write(fileoff - 0x80);//Data Offset - 0x80
                z++;
            }

            long countinfo = newFile.Tell();
            newFile.Write(files.Length);//Count is written there afaik
            long infopointer = newFile.Tell();
            Console.WriteLine("Adding dummy FileInfos...");

            infos.Seek(0, SeekOrigin.Begin);
            var infopos = newFile.Tell();
            newFile.Write(infos.ToArray());

            Console.WriteLine("Rewriting header...");
            long metapos = newFile.Tell();
            newFile.Seek(4, SeekOrigin.Begin);
            newFile.Write((uint)metapos - 0x20);

            newFile.Seek(metapos, SeekOrigin.Begin);

            Console.WriteLine("Adding FileInfos pointer...");
            for (int i = 0; i < files.Length; i++)
            {
                newFile.Write((uint)((infopointer + i * 16) - 0x20));
            }

            Console.WriteLine("Adding Advanced pointers...");

            newFile.Write((uint)0x60);
            newFile.Write(0);
            newFile.Write((uint)(countinfo - 0x20));
            newFile.Write((uint)5);
            newFile.Write((uint)(countinfo + 4 - 0x20));
            newFile.Write((uint)0xB);
            for(int i = 0; i < files.Length; i++)
            {
                newFile.Write((uint)((countinfo + 4) + i * 16 ) - 0x20);

                //Second pointer is a bit more complicated
                if (i == 0)
                {
                    newFile.Write((uint)0x10);
                }
                else
                {
                    if (i == 1)
                    {
                        newFile.Write((uint)0x1C);
                    }
                    else
                    {
                        newFile.Write((uint)(0x1C + (10 * (i - 1))));//Currently this pointer is unknown, so we assume blindly that a basic pattern is correct
                    }
                }
            }

            //This need to be reversed!
            //0, 5, 0B, 10, 1C, 26, 30, 3A, 44, 4E
            //+5, +6, +4, +12, +10, +10, +10, +10, +10

            Console.WriteLine("Adding Filenames...");
            var datcount = new byte[] { 0x44, 0x61, 0x74, 0x61, 0x00, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x00, 0x49, 0x6E, 0x66, 0x6F, 0x00 };
            newFile.Write(datcount);
            int y = 0;

            foreach (string fileName in files)
            {
                FileInfos.Seek(y * 16, SeekOrigin.Begin);
                long namepos = newFile.Tell();
                FileInfos.Write((uint)namepos - 0x20);
                newFile.Write(ShiftJIS.GetBytes(Path.GetFileName(fileName)));
                newFile.Write(nil);
                y++;
            }
            Console.WriteLine("Rewriting FileInfos...");
            newFile.Seek(infopos, SeekOrigin.Begin);

            infos.Seek(0, SeekOrigin.Begin);
            newFile.Write(infos.ToArray());

            Console.WriteLine("Finishing the job...");
            newFile.Seek(0, SeekOrigin.Begin);
            UInt32 newlength = (UInt32)newFile.BaseStream.Length;
            newFile.Write(newlength);

            Console.WriteLine( "Done!");
            newFile.Close();
        }
Пример #5
0
 private void AddPatch(Stream ms, string patchname = "")
 {
     using (var br = new BinaryStream(ms, Encoding.ASCII, leaveOpen: true))
     {
         if (br.ReadUInt32() != 0x5032484b)
         {
             br.Seek(0, SeekOrigin.Begin);
             if (br.ReadUInt32() != 0x5132484b)
             {
               br.Seek(0, SeekOrigin.Begin);
               if (br.ReadUInt32() != 0x4632484b)
               {
                 br.Close();
                 ms.Close();
                 throw new InvalidDataException("Invalid KH2Patch file!");
               }
               else
               {
                 fast_patch=true;
                 Console.WriteLine("Fast patch and dev flags detected! You might get some issues with those!");
               }
             }
         }
         patchms.Add(ms);
         uint oaAuther = br.ReadUInt32(),
             obFileCount = br.ReadUInt32(),
             num = br.ReadUInt32();
         patchname = Path.GetFileName(patchname);
         try
         {
             string author = br.ReadCString();
             Console.ForegroundColor = ConsoleColor.Cyan;
             Console.WriteLine("Loading patch {0} version {1} by {2}", patchname, num, author);
             Console.ResetColor();
             br.Seek(oaAuther, SeekOrigin.Begin);
             uint os1 = br.ReadUInt32(),
                 os2 = br.ReadUInt32(),
                 os3 = br.ReadUInt32();
             br.Seek(oaAuther + os1, SeekOrigin.Begin);
             num = br.ReadUInt32();
             if (num > 0)
             {
                 br.Seek(num*4, SeekOrigin.Current);
                 Console.WriteLine("Changelog:");
                 Console.ForegroundColor = ConsoleColor.Green;
                 while (num > 0)
                 {
                     --num;
                     Console.WriteLine(" * {0}", br.ReadCString());
                 }
             }
             br.Seek(oaAuther + os2, SeekOrigin.Begin);
             num = br.ReadUInt32();
             if (num > 0)
             {
                 br.Seek(num*4, SeekOrigin.Current);
                 Console.ResetColor();
                 Console.WriteLine("Credits:");
                 Console.ForegroundColor = ConsoleColor.Green;
                 while (num > 0)
                 {
                     --num;
                     Console.WriteLine(" * {0}", br.ReadCString());
                 }
                 Console.ResetColor();
             }
             br.Seek(oaAuther + os3, SeekOrigin.Begin);
             author = br.ReadCString();
             if (author.Length != 0)
             {
                 Console.WriteLine("Other information:\r\n");
                 Console.ForegroundColor = ConsoleColor.Green;
                 Console.WriteLine("{0}", author);
             }
             Console.ResetColor();
         }
         catch (Exception e)
         {
             Console.ForegroundColor = ConsoleColor.Red;
             Console.WriteLine("Error reading kh2patch header: {0}: {1}\r\nAttempting to continue files...",
                 e.GetType(), e.Message);
             Console.ResetColor();
         }
         Console.WriteLine("");
         br.Seek(obFileCount, SeekOrigin.Begin);
         num = br.ReadUInt32();
         while (num > 0)
         {
             --num;
             var nPatch = new Patch();
             nPatch.Hash = br.ReadUInt32();
             oaAuther = br.ReadUInt32();
             nPatch.CompressedSize = br.ReadUInt32();
             nPatch.UncompressedSize = br.ReadUInt32();
             nPatch.Parent = br.ReadUInt32();
             nPatch.Relink = br.ReadUInt32();
             nPatch.Compressed = br.ReadUInt32() != 0;
             nPatch.IsNew = br.ReadUInt32() == 1; //Custom
             if (!nPatch.IsRelink)
             {
                 if (nPatch.CompressedSize != 0)
                 {
                     nPatch.Stream = new Substream(ms, oaAuther, nPatch.CompressedSize);
                 }
                 else
                 {
                     throw new InvalidDataException("File length is 0, but not relinking.");
                 }
             }
             // Use the last file patch
             if (patches.ContainsKey(nPatch.Hash))
             {
                 Console.ForegroundColor = ConsoleColor.Red;
     #if DEBUG
                 Console.WriteLine("The file {0} has been included multiple times. Using the one from {1}.",
                     HashList.HashList.NameFromHash(nPatch.Hash), patchname);
     #endif
                 patches[nPatch.Hash].Dispose();
                 patches.Remove(nPatch.Hash);
                 Console.ResetColor();
             }
             patches.Add(nPatch.Hash, nPatch);
             //Global checks
             if (!KH2Changed && nPatch.IsInKH2 || nPatch.IsInKH2Sub)
             {
                 KH2Changed = true;
             }
             else if (!OVLChanged && nPatch.IsInOVL)
             {
                 OVLChanged = true;
             }
             else if (!ISOChanged && nPatch.IsinISO)
             {
                 ISOChanged = true;
             }
             if (nPatch.IsNew)
             {
                 AddToNewFiles(nPatch);
             }
             br.Seek(60, SeekOrigin.Current);
         }
     }
 }