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); }
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}"); }