private static void WriteProgress(int line, ref int lastLineLength, ExkifintArgs args)
        {
            Console.CursorLeft = 0;
            Console.CursorTop  = line;
            string newLine =
                $"[{args.Percent.ToString("00.00")}%]" +
                $"[{Math.Min(args.FileCount, args.FileIndex + 1)}/{args.FileCount}]" +
                $"[{args.Ellapsed.ToString(@"hh\:mm\:ss")}]" +
                $" {args.FileName}";

            if (newLine.Length > Console.BufferWidth)
            {
                newLine = newLine.Substring(0, Console.BufferWidth);
            }
            if (lastLineLength > newLine.Length)
            {
                newLine += new string(' ', lastLineLength - newLine.Length);
            }
            lastLineLength = newLine.Length;
            Console.Write(newLine);
        }
Exemplo n.º 2
0
        private static void Run(Stream stream, string intFile, string exeFile,
                                string outputDir, ExkifintCallback progress = null)
        {
            Stopwatch watch     = Stopwatch.StartNew();
            DateTime  startTime = DateTime.UtcNow;
            string    gameId    = FindVCode2(exeFile);


            BinaryReader reader = new BinaryReader(stream);
            KIFHDR       hdr    = reader.ReadStruct <KIFHDR>();

            if (hdr.Signature != "KIF")             // It's really a KIF INT file
            {
                throw new InvalidFileException(Path.GetFileName(intFile), "INT");
            }

            KIFENTRY[] entries = reader.ReadStructArray <KIFENTRY>(hdr.EntryCount);

            uint tocSeed = GenTocSeed(gameId);
            uint fileKey = 0;
            bool decrypt = false;

            /*const string fileName = "bom_s.hg3";
             * const uint offset = 1112718577;
             * const int length = 1907629000;
             * const uint fileKey2 = 1457527205;
             * KIFENTRY kifEntry = new KIFENTRY {
             *      FileNameRaw = new char[64],
             *      Offset = offset,
             *      Length = length,
             * };
             * Array.Copy(fileName.ToCharArray(), kifEntry.FileNameRaw, fileName.Length);
             * DecryptEntry(ref kifEntry, fileKey2);*/

            ExkifintArgs args = new ExkifintArgs();

            for (int i = 0; i < hdr.EntryCount; i++)
            {
                if (entries[i].FileName == "__key__.dat")
                {
                    if (!decrypt)
                    {
                        //MersenneTwister.Seed(entries[i].Length);
                        //fileKey = MersenneTwister.GenRand();
                        fileKey = MersenneTwister.GenRand(entries[i].Length);
                        decrypt = true;
                    }
                }
                else
                {
                    args.FileCount++;
                }
            }

            DateTime  lastRefresh = DateTime.MinValue;
            Stopwatch writeTime   = new Stopwatch();
            TimeSpan  refreshTime = TimeSpan.FromMilliseconds(20);

            //Stopwatch processTime = new Stopwatch();
            for (uint i = 0; i < hdr.EntryCount; i++)
            {
                if (entries[i].FileName == "__key__.dat")
                {
                    continue;
                }

                if (decrypt)
                {
                    UnobfuscateFileName(entries[i].FileNameRaw, tocSeed + i);
                    //UnobfuscateFileName(ref entries[i].FileName, tocSeed + i);

                    entries[i].Offset += i;

                    DecryptEntry(ref entries[i].Info, fileKey);

                    /*Blowfish bf = new Blowfish();
                     * bf.Set_Key((byte*) &file_key, 4);
                     * byte[] entry_buff = entries[i].bytes;
                     * bf.Decrypt(entry_buff, 8);
                     * entries[i].bytes = entry_buff;*/
                }

                args.Ellapsed = DateTime.UtcNow - startTime;
                // Round to nearest hundredth
                args.Percent  = Math.Round((double)args.FileIndex / args.FileCount * 10000) / 100;
                args.FileName = entries[i].FileName;
                TimeSpan sinceRefresh = DateTime.UtcNow - lastRefresh;
                if (sinceRefresh >= refreshTime)
                {
                    lastRefresh = DateTime.UtcNow;
                    writeTime.Start();
                    progress?.Invoke(args);
                    writeTime.Stop();
                }

                //processTime.Restart();
                stream.Position = entries[i].Offset;
                byte[] buffer = reader.ReadBytes(entries[i].Length);

                if (decrypt)
                {
                    DecryptData(buffer, entries[i].Length, fileKey);

                    /*Blowfish bf = new Blowfish();
                     * bf.Set_Key((byte*)&file_key, 4);
                     * bf.Decrypt(buff, (len / 8) * 8);*/
                }

                string path = Path.Combine(outputDir, entries[i].FileName);
                File.WriteAllBytes(path, buffer);
                args.FileIndex++;
                //processTime.Stop();
                //if (processTime.ElapsedMilliseconds >= 500)
                //	Trace.WriteLine($"Large File: {buffer.Length / 1024:###,###,###,###}KB [{processTime.ElapsedMilliseconds}ms]");
            }

            args.Ellapsed = DateTime.UtcNow - startTime;
            args.Percent  = 100.0;
            progress?.Invoke(args);
            Trace.WriteLine($"Console Write Time: {writeTime.Elapsed:mm\\:ss\\.fff}");
        }