Beispiel #1
0
        private static uint GetFileAsInput(out string name, out bool blank)
        {
            string inp;

            if (!uselog)
            {
                inp = Console.ReadLine().Replace("\"", "").Trim();
            }
            else
            {
                inp = logfile.ReadLine().Replace("\"", "").Trim();
            }
            uint hash;

            name = "";
            if (inp.Length == 0)
            {
                blank = true;
                return(0);
            }
            blank = false;
            if (inp.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
            {
                if (uint.TryParse(inp.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hash))
                {
                    name = KH1FM_Toolkit.HashList.NameFromHash(hash);
                }
                else
                {
                    ISOTP.WriteWarning("Error: Failed to parse as hex number.");
                    return(0);
                }
            }
            else
            {
                hash = KH1FM_Toolkit.PatchManager.calcHash(inp);
                //Check hashpairs anyway, and warn if something unexpected returns
                if (!hvs)
                {
                    if (!KH1FM_Toolkit.HashList.pairs.TryGetValue(hash, out name))
                    {
                        Console.WriteLine(" Warning: Filename not found into the Hashlist.");
                    }
                    else if (name != inp)
                    {
                        ISOTP.WriteWarning(" Warning: Hash conflict with {0}; both contain the same hash.", name);
                    }
                    name = inp;
                }
            }
            return(hash);
        }
Beispiel #2
0
        internal static void Mainp(string[] args)
        {
            bool log = false;

            Console.Title = KH1FM_Toolkit.KH1ISOReader.program.ProductName + " " + KH1FM_Toolkit.KH1ISOReader.program.FileVersion + " [" +
                            KH1FM_Toolkit.KH1ISOReader.program.CompanyName + "]";
            var  patch      = new PatchFile();
            bool encrypt    = true,
                 batch      = false,
                 authorSet  = false,
                 verSet     = false,
                 changeSet  = false,
                 creditSet  = false,
                 otherSet   = false;
            string output   = "output.kh1patch";
            string logtouse = "none";

            for (int i = 0; i < args.Length; ++i)
            {
                switch (args[i].ToLowerInvariant())
                {
                case "-batch":
                    batch = true;
                    break;

                case "-log":
                    log = true;
                    break;

#if DEBUG
                case "-decrypted":
                    if (encrypt)
                    {
                        encrypt = false;
                        Console.WriteLine("Writing in decrypted mode!");
                    }
                    break;
#endif
                case "-hashverskip":
                    hvs = true;
                    break;

                case "-version":
                    if (!uint.TryParse(args[++i].Trim(), out patch.Version))
                    {
                        patch.Version = 1;
                    }
                    else
                    {
                        verSet = true;
                    }
                    break;

                case "-author":
                    patch.Author = args[++i];
                    authorSet    = true;
                    break;

                case "-other":
                    patch.OtherInfo = args[++i];
                    otherSet        = true;
                    break;

                case "-uselog":
                    logtouse = args[++i];
                    uselog   = true;
                    break;

                case "-changelog":
                    patch.AddChange(args[++i]);
                    break;

                case "-skipchangelog":
                    changeSet = true;
                    break;

                case "-credits":
                    patch.AddCredit(args[++i]);
                    break;

                case "-skipcredits":
                    creditSet = true;
                    break;

                case "-output":
                    output = args[++i];
                    if (!output.EndsWith(".kh1patch", StringComparison.InvariantCultureIgnoreCase))
                    {
                        output += ".kh1patch";
                    }
                    break;
                }
            }
            //TODO MENU
            if (log)
            {
                var filestream   = new FileStream("log.log", FileMode.Create);
                var streamwriter = new StreamWriter(filestream);
                streamwriter.AutoFlush = true;
                Console.SetOut(streamwriter);
                Console.SetError(streamwriter);
            }
            if (!batch)
            {
                Console.ForegroundColor = ConsoleColor.Gray;
                DateTime builddate = RetrieveLinkerTimestamp();
                Console.Write("{0}\nBuild Date: {2}\nVersion {1}", KH1FM_Toolkit.KH1ISOReader.program.ProductName,
                              KH1FM_Toolkit.KH1ISOReader.program.FileVersion, builddate);
                Console.ResetColor();
#if DEBUG
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("\nPRIVATE RELEASE\n");
                Console.ResetColor();
#else
                Console.Write("\nPUBLIC RELEASE\n");
#endif
                Console.ForegroundColor = ConsoleColor.DarkMagenta;
                Console.Write("\nProgrammed by {0}\nhttp://www.govanify.blogspot.fr\nhttp://www.govanify.x10host.com",
                              KH1FM_Toolkit.KH1ISOReader.program.CompanyName);
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.Write(
                    "\n\nThis tool is able to create patches for the software KH1FM_Toolkit.\nIt can add files using the internal compression of the game \nKingdom Hearts 1(Final Mix), relink files to others, recreate\nthe iso without size limits and without corruption.\nThis patch system is the best ever made for this game atm.\n");
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("\nPress enter to run using the file:");
                Console.ResetColor();
                Console.Write(" {0}", output);

                if (!batch)
                {
                    Console.ReadLine();
                }
            }
            if (uselog)
            {
                logfile = new System.IO.StreamReader(logtouse);
            }
            KH1FM_Toolkit.HashList.loadHashPairs(printInfo: true);
            if (!authorSet)
            {
                Console.Write("Enter author's name: ");
                if (!uselog)
                {
                    patch.Author = Console.ReadLine().Trim();
                }
                else
                {
                    patch.Author = logfile.ReadLine().Trim();
                }
            }
            if (!verSet)
            {
                Console.Write("Enter revision number: ");
                if (!uselog)
                {
                    while (!uint.TryParse(Console.ReadLine().Trim(), out patch.Version))
                    {
                        ISOTP.WriteWarning("\nInvalid number! ");
                    }
                }
                else
                {
                    while (!uint.TryParse(logfile.ReadLine().Trim(), out patch.Version))
                    {
                        ISOTP.WriteWarning("\nInvalid number! ");
                    }
                }
            }
            if (!changeSet)
            {
                Console.WriteLine("Enter changelog lines here (leave blank to continue):");
                do
                {
                    string inp;
                    if (!uselog)
                    {
                        inp = Console.ReadLine();
                    }
                    else
                    {
                        inp = logfile.ReadLine();
                    }
                    if (inp.Length == 0)
                    {
                        break;
                    }
                    patch.AddChange(inp);
                } while (true);
            }
            if (!creditSet)
            {
                Console.WriteLine("Enter credits here (leave blank to continue):");
                do
                {
                    string inp;
                    if (!uselog)
                    {
                        inp = Console.ReadLine();
                    }
                    else
                    {
                        inp = logfile.ReadLine();
                    }
                    if (inp.Length == 0)
                    {
                        break;
                    }
                    patch.AddCredit(inp);
                } while (true);
            }
            if (!otherSet)
            {
                Console.Write("Other information (leave blank to continue): ");
                string inp2 = "";
                bool   flag = false;
                do
                {
                    string inp;
                    if (!uselog)
                    {
                        inp = Console.ReadLine();
                    }
                    else
                    {
                        inp = logfile.ReadLine();
                    }
                    if (inp.Length == 0)
                    {
                        break;
                    }
                    if (flag)
                    {
                        inp2 += "\n" + inp;
                    }
                    else
                    {
                        inp2 += inp;
                    }
                    flag = true;
                } while (true);
                patch.OtherInfo = inp2;
            }
#if DEBUG
            Console.WriteLine("Filenames may be formatted as text (al.wdt) or hash (0x0004f44b).");
#endif
            do
            {
                var file = new PatchFile.FileEntry();
                Console.Write("\nEnter filename: ");
                string name, rel;
                //Target file
                file.Hash = GetFileAsInput(out name, out otherSet);
                if (otherSet)
                {
                    break;
                }
                Console.WriteLine("  Using \"{0}\" for {1:X8}", name, file.Hash);
                //Relink
                Console.Write("Relink to this filename(ex: al00_07.img) [Blank for none]: ");
                file.Relink = GetFileHashAsInput(out rel);
                if (file.Relink == 0)
                {
                    try
                    {
                        file.Data = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read);
                    }
                    catch (Exception e)
                    {
                        ISOTP.WriteWarning("Failed opening the file: " + e.Message);
                        continue;
                    }
                    file.name = Path.GetFileName(name);
                    if (file.Data.Length > int.MaxValue || file.Data.Length < 10)
                    {
                        ISOTP.WriteWarning("Too {0} to compress. Press enter.",
                                           (file.Data.Length < 10 ? "small" : "big"));
                        //Do this so the line count is the same whether we can compress or not.
                        Console.ReadLine();
                    }
                    else
                    {
                        //Compress
                        Console.Write("Compress this file? [Y/n] ");
                        file.IsCompressed = GetYesNoInput();
                    }
                }
                else
                {
                    Console.WriteLine("  Using \"{0}\" for {1:X8}", rel, file.Relink);
                }
                //Parent
                Console.Write("Parent compressed file [Leave blank for KINGDOM]: ");
                file.ParentHash = GetFileHashAsInput(out rel);
                if (rel.Equals("KINGDOM", StringComparison.InvariantCultureIgnoreCase))
                {
                    file.ParentHash = 0;
                }
                else if (rel.Equals("ISO", StringComparison.InvariantCultureIgnoreCase))
                {
                    file.ParentHash = 2;
                }
                else
                {
                    switch (file.ParentHash)
                    {
                    case 0:
                        rel = "KINGDOM";
                        break;

                    case 1:
                        rel = "ISO";
                        break;
                    }
                }
                Console.WriteLine("  Using \"{0}\" for {1:X8}", rel, file.ParentHash);
                //IsNew
                Console.Write("Should this file be added if he's not in the game? [y/N] ");
                file.IsNewFile = GetYesNoInput();
                patch.Files.Add(file);
            } while (true);
            try
            {
                //TODO Compress(buffer>magic>Compress>Write to output). Files are already compressed, I need to look at this later
                using (FileStream fs = File.Open(output, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    if (encrypt)
                    {
                        patch.Write(fs);
                    }
                    else
                    {
                        patch.WriteDecrypted(fs);
                    }
                    if (batch)
                    {
                        Environment.Exit(0);
                    }
                }
            }
            catch (Exception e)
            {
                ISOTP.WriteWarning("Failed to save file: " + e.Message);
                ISOTP.WriteWarning(e.StackTrace);
                try
                {
                    File.Delete("output.kh1patch");
                }
                catch (Exception z)
                {
                    ISOTP.WriteWarning("Failed to delete file: " + z.Message);
                }
            }
            if (!batch)
            {
                Console.Write("Press enter to exit...");
                Console.ReadLine();
                Environment.Exit(0);
            }
        }
Beispiel #3
0
        public void WriteDecrypted(Stream stream)
        {
            stream.Position = 0;
            uint changeLen = 0, creditLen = 0;

            changeLen = Changelogs.Aggregate(changeLen, (current, b) => current + (4 + (uint)b.Length));
            creditLen = Credits.Aggregate(creditLen, (current, b) => current + (4 + (uint)b.Length));
            using (var bw = new BinaryStream(stream, leaveOpen: true))
            {
                uint i;
                bw.Write(Signature);
                bw.Write((uint)(16 + _Author.Length));
                bw.Write((uint)(16 + _Author.Length + 16 + changeLen + 4 + creditLen + _OtherInfo.Length));
                bw.Write(Version);
                bw.Write(_Author);
                bw.Write((uint)12);
                bw.Write(16 + changeLen);
                bw.Write(16 + changeLen + 4 + creditLen);
                bw.Write(i = (uint)Changelogs.Count);
                i         *= 4;
                foreach (var b in Changelogs)
                {
                    bw.Write(i);
                    i += (uint)b.Length;
                }
                foreach (var b in Changelogs)
                {
                    bw.Write(b);
                }
                bw.Write(i = (uint)Credits.Count);
                i         *= 4;
                foreach (var b in Credits)
                {
                    bw.Write(i);
                    i += (uint)b.Length;
                }
                foreach (var b in Credits)
                {
                    bw.Write(b);
                }
                bw.Write(_OtherInfo);
                bw.Write((uint)Files.Count);

                //Check total size to add
                long fileTotal = 0;
                try
                {
                    fileTotal = Files.Where(file => file.Relink == 0)
                                .Aggregate(fileTotal, (current, file) => checked (current + file.Data.Length));
                }
                catch (OverflowException)
                {
                    ISOTP.WriteError(
                        "That's WAY too much file data... is there even that much in the gameo.O?\r\nTry to split up the patch...");
                    return;
                }
                Stream filedata = null;
                string filename = null;
                //Use a MemoryStream if we can, much cleaner\faster
                if (fileTotal <= int.MaxValue)
                {
                    try
                    {
                        filedata = new MemoryStream((int)fileTotal);
                    }
                    catch (OutOfMemoryException)
                    {
                        filedata = null;
                        ISOTP.WriteWarning("Failed to allocate enough memory, trying temporary file fallback...");
                    }
                }
                //If we can't use a MemStream (or that failed), try a FileStream as a temp file
                if (filedata == null)
                {
                    filename = Path.GetTempFileName();
                    Console.WriteLine("Wow there's a lot of file data! Using a temporary file now!\r\nUsing {0}",
                                      filename);
                    filedata = File.Open(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
                }
                using (filedata)
                {
                    i = (uint)(stream.Position + Files.Count * 92);
                    foreach (FileEntry file in Files)
                    {
                        bw.Write(file.Hash);
                        if (file.Relink != 0)
                        {
                            bw.Write((uint)0);
                            bw.Write((uint)0);
                            bw.Write((uint)0);
                            bw.Write(file.ParentHash);
                            bw.Write(file.Relink);
                            bw.Write((uint)0);
                        }
                        else
                        {
                            uint cSize;
                            file.Data.Position = 0;
                            if (file.IsCompressed)
                            {
                                try
                                {
                                    var input = new byte[file.Data.Length];
                                    file.Data.Read(input, 0, (int)file.Data.Length);
                                    Console.Write("Compressing {0}: ",
                                                  file.name ?? file.Hash.ToString("X8"));
                                    byte[] output       = KH1Compressor.compress(input);
                                    uint   cSizeSectors = (uint)Math.Ceiling((double)output.Length / 2048) - 1;
                                    if (output.LongLength > int.MaxValue)
                                    {
                                        throw new NotSupportedException(
                                                  "Compressed data too big to store (Program limitation)");
                                    }
                                    if (cSizeSectors > 0x2FFF)
                                    {
                                        throw new NotSupportedException(
                                                  "Compressed data too big to store (IDX limitation)");
                                    }
                                    if ((cSizeSectors & 0x1000u) == 0x1000u)
                                    {
                                        throw new NotSupportedException(
                                                  "Compressed data size hit 0x1000 bit limitation (IDX limitation)");
                                    }
                                    cSize = (uint)output.Length;
                                    filedata.Write(output, 0, output.Length);
                                }
                                catch (NotCompressableException e)
                                {
                                    string es = "ERROR: Failed to compress file: " + e.Message;
                                    ISOTP.WriteWarning(es);
                                    Console.Write("Add it without compressing? [Y/n] ");
                                    if (Program.GetYesNoInput())
                                    {
                                        file.IsCompressed  = false;
                                        cSize              = (uint)file.Data.Length;
                                        file.Data.Position = 0; //Ensure at beginning
                                        file.Data.CopyTo(filedata);
                                    }
                                    else
                                    {
                                        throw new NotCompressableException(es, e);
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("Adding {0}", file.name ?? file.Hash.ToString("X8"));
                                cSize = (uint)file.Data.Length;
                                file.Data.Position = 0; //Ensure at beginning
                                file.Data.CopyTo(filedata);
                            }
                            if (!file.IsCompressed &&
                                (((uint)Math.Ceiling((double)cSize / 2048) - 1) & 0x1000u) == 0x1000u)
                            {
                                ISOTP.WriteWarning(
                                    "Data size hit 0x1000 bit limitation, but this file may be OK if it's streamed.");
                            }
                            bw.Write(i);
                            i += cSize;
                            bw.Write(cSize);
                            bw.Write((uint)file.Data.Length);
                            bw.Write(file.ParentHash);
                            bw.Write((uint)0);
                            bw.Write((uint)(file.IsCompressed ? 1 : 0));
                        }
                        bw.Write((uint)(file.IsNewFile ? 1 : 0));  //Custom
                        //Padding
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                        bw.Write((uint)0);
                    }
                    filedata.Position = 0; //Ensure at beginning
                    filedata.CopyTo(stream);
                }
                //If we used a temp file, delete it
                if (filename != null)
                {
                    File.Delete(filename);
                }
            }
        }