public void ReadFile(IDXFile.IDXEntry entry, Stream target, bool AdSize) { if (entry.IsCompressed) { if (entry.CompressedDataLength > int.MaxValue) { throw new NotSupportedException("File to big to decompress"); } var input = new byte[entry.CompressedDataLength]; Seek(entry.DataLBA); file.Read(input, 0, (int)entry.CompressedDataLength); try { byte[] output = KH2Compressor.decompress(input, entry.DataLength); target.Write(output, 0, output.Length); if (AdSize) { Console.WriteLine("Size (unpacked): {0}\r\n", output.Length); } } catch (Exception e) { Program.WriteError(" ERROR: Failed to decompress: " + e.Message); } } else { ReadFileBuffer(target, entry.Offset, entry.DataLength); } }
public void WriteDecrypted(Stream stream) { ConsoleProgress consoleProgress = null; if (!Program.oldui) { consoleProgress = new ConsoleProgress(Files.Count, "Creating kh2patch...", ConsoleColor.Green); } 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; if (!fast_patch) { bw.Write(Signature); } else { bw.Write(Signature_Fast); } 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); if (Program.oldui) { Console.Write("Compressing {0}: ", file.name ?? file.Hash.ToString("X8")); } else { if (Program.UISwitch) { consoleProgress.Text = string.Format("Compressing {0}", file.name ?? file.Hash.ToString("X8")); } else { decimal nmbpercent = (((decimal)consoleProgress.Current / (decimal)consoleProgress.Total) * 100); consoleProgress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } consoleProgress.Increment(1L); } byte[] output = KH2Compressor.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 { if (Program.oldui) { Console.WriteLine("Adding {0}", file.name ?? file.Hash.ToString("X8")); } else { if (Program.UISwitch) { consoleProgress.Text = string.Format("Adding {0}", file.name ?? file.Hash.ToString("X8")); } else { decimal nmbpercent = (((decimal)consoleProgress.Current / (decimal)consoleProgress.Total) * 100); consoleProgress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } consoleProgress.Increment(1L); } 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); } if (Program.oldui) { Console.WriteLine("Patch created."); } else { consoleProgress.Text = "Patch created."; consoleProgress.Finish(); } } }