/// <param name="idx">Left open.</param> /// <param name="img">Left open.</param> /// <param name="recurse">recursive</param> /// <param name="tfolder">Complete name</param> /// <param name="name">Complete name</param> private static void ExtractIDX(IDXFile idx, Stream img, ConsoleProgress progress, bool recurse = false,string tfolder = "export/", string name = "") { using (var imgf = new IMGFile(img, leaveOpen: true)) { var idxs = new List<Tuple<IDXFile, string>>(); uint i = 0, total = idx.Count; progress.Total += total; foreach (IDXFile.IDXEntry entry in idx) { string filename = entry.FileName(); if (recurse) { switch (entry.Hash) { case 0x0499386d: //000hb.idx case 0x0b2025ed: //000mu.idx case 0x2b87c9dc: //000di.idx case 0x2bb6ecb2: //000ca.idx case 0x35f6154a: //000al.idx case 0x3604eeef: //000tt.idx case 0x43887a92: //000po.idx case 0x4edb9e9e: //000gumi.idx case 0x608e02b4: //000es.idx case 0x60dd6d06: //000lk.idx case 0x79a2a329: //000eh.idx case 0x84eaa276: //000tr.idx case 0x904a97e0: //000wm.idx case 0xb0be1463: //000wi.idx case 0xd233219f: //000lm.idx case 0xe4633b6f: //000nm.idx case 0xeb89495d: //000bb.idx case 0xf87401c0: //000dc.idx case 0xff7a1379: //000he.idx idxs.Add(new Tuple<IDXFile, string>(new IDXFile(imgf.GetFileStream(entry)), Path.GetFileNameWithoutExtension(filename).Substring(3))); Debug.WriteLine(" Added IDX to list"); break; } } if (_advanced) { if (name == "KH2") { Console.WriteLine("-----------File {0,4}/{1}, using {2}.IDX\n", ++i, total, name); } else { if (name == "OVL") { Console.WriteLine("-----------File {0,4}/{1}, using {2}.IDX\n", ++i, total, name); } else { Console.WriteLine("-----------File {0,4}/{1}, using 000{2}.idx\n", ++i, total, name); } } Console.WriteLine("Dual Hash flag: {0}", entry.IsDualHash); //Always false but anyways Console.WriteLine("Hashed filename: {0}\nHashAlt: {1}", entry.Hash, entry.HashAlt); Console.WriteLine("Compression flags: {0}", entry.IsCompressed); Console.WriteLine("Size (packed): {0}", entry.CompressedDataLength); Console.WriteLine("Real name: {0}", filename); } else { if(oldui) { Console.WriteLine("[{2}: {0,4}/{1}]\tExtracting {3}", ++i, total, name, filename); } else { if (progress != null) { if (UISwitch) { progress.Text = string.Format("Extracting [{0}] {1}", name, filename); } else { decimal nmbpercent = (((decimal)progress.Current / (decimal)progress.Total) * 100); progress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } progress.Increment(1L); } } } filename = Path.GetFullPath(tfolder + filename); Directory.CreateDirectory(Path.GetDirectoryName(filename)); using (var output = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { bool adSize = _advanced; imgf.ReadFile(entry, output, adSize); } } if (recurse && idxs.Count != 0) { foreach (var sidx in idxs) { ExtractIDX(sidx.Item1, img, progress, false, tfolder, sidx.Item2); } } } }
/// <param name="sidx">Stream of the original idx.</param> /// <param name="simg">Stream of the original img.</param> /// <param name="timg">img of the new iso.</param> /// <param name="imgOffset">Offset of the new img in the new iso.</param> /// <param name="parenthash">Parent Hash(KH2 or OVL or 000's)</param> private static MemoryStream PatchIDXInternal(Stream sidx, Stream simg, Stream timg, long imgOffset,ConsoleProgress progress, uint parenthash = 0) { //Generate Parent name string parentname; if (parenthash == 0) { parentname = "KH2"; } else if (parenthash == 1) { parentname = "OVL"; } #if !RELEASE else if (HashList.HashList.pairs.TryGetValue(parenthash, out parentname)) { parentname = parentname.Substring(3, parentname.IndexOf('.') - 3); } else { parentname = parenthash.ToString("X8"); } #else parentname = parenthash.ToString("X8"); #endif //Need more using using (var idx = new IDXFile(sidx, leaveOpen: true)) using (var img = new IMGFile(simg, leaveOpen: true)) using (var npair = new IDXIMGWriter(timg, imgOffset, true)) { progress.Total += (long)((ulong)idx.Count); uint i = 0, total = idx.Count; foreach (IDXFile.IDXEntry file in idx) { if (oldui) { if (UISwitch) { Console.Write("[{0}: {1,4}/{2}]\t{3}", parentname, ++i, total, file.FileName()); } else { Console.Write("[{0}: {1,4}/{2}]\t{3}", parentname, ++i, total, file.Hash.ToString("X8")); } } else { if (UISwitch) { progress.Text = string.Format("Adding [{0}] {1}", parentname, file.FileName()); } else { decimal nmbpercent = (((decimal)progress.Current / (decimal)progress.Total) * 100); progress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } progress.Increment(1L); } switch (file.Hash) { case 0x0499386d: //000hb.idx case 0x0b2025ed: //000mu.idx case 0x2b87c9dc: //000di.idx case 0x2bb6ecb2: //000ca.idx case 0x35f6154a: //000al.idx case 0x3604eeef: //000tt.idx case 0x43887a92: //000po.idx case 0x4edb9e9e: //000gumi.idx case 0x608e02b4: //000es.idx case 0x60dd6d06: //000lk.idx case 0x79a2a329: //000eh.idx case 0x84eaa276: //000tr.idx case 0x904a97e0: //000wm.idx case 0xb0be1463: //000wi.idx case 0xd233219f: //000lm.idx case 0xe4633b6f: //000nm.idx case 0xeb89495d: //000bb.idx case 0xf87401c0: //000dc.idx case 0xff7a1379: //000he.idx if (oldui) { Console.WriteLine("\tRe-Building..."); } using (Substream oidx = img.GetFileStream(file)) using (MemoryStream subidx = PatchIDXInternal(oidx, simg, timg, imgOffset, progress, file.Hash)) { npair.AddFile(new IDXFile.IDXEntry { Hash = file.Hash, HashAlt = file.HashAlt, IsDualHash = file.IsDualHash, DataLength = (uint) subidx.Length, IsCompressed = false, CompressedDataLength = (uint) subidx.Length }, subidx); } continue; } PatchManager.Patch patch; // Could make sure the parents match perfectly, but there's only 1 of every name anyway. // So I'll settle for just making sure the file isn't made for the ISO. if (Patches.patches.TryGetValue(file.Hash, out patch) && /*patch.Parent == parenthash*/ !patch.IsinISO) { patch.IsNew = false; if (patch.IsRelink) { try { npair.RelinkFile(file.Hash, patch.Relink); if (oldui) { Console.WriteLine("\tRelinking..."); } } catch { progress.Total -= 1L; if (oldui) { Console.WriteLine("\tDeferred Relinking..."); } // Add the patch to be processed later, in the new file block patch.Parent = parenthash; Patches.AddToNewFiles(patch); } continue; } if (oldui) { Console.WriteLine("\tPatching..."); } #if extract Console.WriteLine("\nEXTRACTING THE FILE!"); Console.WriteLine("\nGetting the name..."); string fname2; HashList.HashList.pairs.TryGetValue(file.Hash, out fname2); Console.WriteLine("\nCreating directory..."); try { Directory.CreateDirectory(Path.GetDirectoryName(fname2)); } catch { Console.WriteLine("\nDirectory is surely null. Trying to create the file anyways..."); } Console.WriteLine("\nCreating the file..."); FileStream fileStream = File.Create(fname2); Console.WriteLine("\nConverting the stream to a byte[]..."); patch.Stream.Position = 0; var buffer = new byte[patch.Stream.Length]; for (int totalBytesCopied = 0; totalBytesCopied < patch.Stream.Length;) totalBytesCopied += patch.Stream.Read(buffer, totalBytesCopied, Convert.ToInt32(patch.Stream.Length) - totalBytesCopied); Console.WriteLine("\nConverting the int to uint..."); byte[] file2; if (patch.Compressed) { Console.WriteLine("\nThe file is compressed!"); Console.WriteLine("\nDecompressing the file..."); file2 = KH2Compressor.decompress(buffer, patch.UncompressedSize); } else { file2 = buffer; } Console.WriteLine("\nOpening the stream for the file.."); Stream decompressed = new MemoryStream(file2); Console.WriteLine("\nCopying the Stream..."); decompressed.CopyTo(fileStream); Console.WriteLine("\nDone!..."); #endif try { npair.AddFile(new IDXFile.IDXEntry { Hash = file.Hash, HashAlt = file.HashAlt, IsDualHash = file.IsDualHash, DataLength = patch.UncompressedSize, IsCompressed = patch.Compressed, CompressedDataLength = patch.CompressedSize }, patch.Stream); continue; } catch (Exception e) { WriteError(" ERROR Patching: " + e.Message); #if DEBUG WriteError(e.StackTrace); #endif } } if (oldui) { Console.WriteLine(""); } npair.AddFile(file, img.GetFileStream(file)); } //Check for new files to add List<uint> newfiles; if (Patches.newfiles.TryGetValue(parenthash, out newfiles)) { progress.Total += (long)newfiles.Count; foreach (uint hash in newfiles) { PatchManager.Patch patch; if (Patches.patches.TryGetValue(hash, out patch) && patch.IsNew) { patch.IsNew = false; string fname; #if !RELEASE if (!HashList.HashList.pairs.TryGetValue(hash, out fname)) { fname = String.Format("@noname/{0:X8}.bin", hash); } #else fname = String.Format("@noname/{0:X8}.bin", hash); #endif if (oldui) { Console.Write("[{0}: NEW]\t{1}", parentname, fname); } else { if (UISwitch) { progress.Text = string.Format("Adding [{0} : NEW] {1}", parentname, fname); } else { decimal nmbpercent = (((decimal)progress.Current / (decimal)progress.Total) * 100); progress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } progress.Increment(1L); } try { if (patch.IsRelink) { if (oldui) { Console.WriteLine("\tAdding link..."); } npair.RelinkFile(hash, patch.Relink); } else { if (oldui) { Console.WriteLine("\tAdding file..."); } npair.AddFile(new IDXFile.IDXEntry { Hash = hash, HashAlt = 0, IsDualHash = false, DataLength = patch.UncompressedSize, IsCompressed = patch.Compressed, CompressedDataLength = patch.CompressedSize }, patch.Stream); } } catch (FileNotFoundException) { Console.WriteLine(" WARNING Failed to find the file to add!"); } catch (Exception e) { WriteError(" ERROR adding file: {0}", e.Message); } } } } return npair.GetCurrentIDX(); } }
/// <param name="isofile">Original ISO</param> /// <param name="nisofile">New ISO file</param> private static void PatchISO(Stream isofile, Stream nisofile) { if (oldui) { using (var iso = new ISOFileReader(isofile)) using (var niso = new ISOCopyWriter(nisofile, iso)) { uint i = 0; Trivalent cKh2 = Patches.KH2Changed ? Trivalent.ChangesPending : Trivalent.NoChanges, cOvl = Patches.OVLChanged ? Trivalent.ChangesPending : Trivalent.NoChanges; bool cIso = Patches.ISOChanged; foreach (FileDescriptor file in iso) { Console.Write("[ISO: {0,4}]\t{1}", ++i, file.FullName); string name = file.FileName; if (name.EndsWith("KH2.IDX") || name.EndsWith("KH2.IMG")) { if (cKh2.HasFlag(Trivalent.ChangesPending)) { cKh2 = Trivalent.Changed; long lpos = niso.file.Position; if (oldui) { Console.WriteLine("\tRe-Building..."); } try { FileDescriptor img = iso.FindFile("KH2.IMG"), idx = iso.FindFile("KH2.IDX"); ConsoleProgress consoleProgress = new ConsoleProgress(1L, null, ConsoleColor.Green, false); using ( MemoryStream ms = PatchIDX(iso.GetFileStream(idx), iso.GetFileStream(img), img, niso, consoleProgress ) ) { idx.RecordingDate = DateTime.UtcNow; niso.AddFile2(idx, ms, name); } continue; } catch (Exception e) { WriteError(" Error creating IDX/IMG: {0}\n{1}", e.Message, e.StackTrace); niso.file.Position = lpos; } } else if (cKh2.HasFlag(Trivalent.Changed)) { Console.WriteLine("\tRe-Built"); continue; } } else if (name.EndsWith("OVL.IDX") || name.EndsWith("OVL.IMG")) { if (cOvl.HasFlag(Trivalent.ChangesPending)) { cOvl = Trivalent.Changed; long lpos = niso.file.Position; Console.WriteLine("\tRe-Building..."); try { FileDescriptor img = iso.FindFile("OVL.IMG"), idx = iso.FindFile("OVL.IDX"); ConsoleProgress consoleProgress = new ConsoleProgress(1L, null, ConsoleColor.Green, false); using ( MemoryStream ms = PatchIDX(iso.GetFileStream(idx), iso.GetFileStream(img), img, niso,consoleProgress, true)) { idx.RecordingDate = DateTime.UtcNow; niso.AddFile2(idx, ms, name); } continue; } catch (Exception e) { WriteError(" Error creating IDX/IMG: " + e.Message); niso.file.Position = lpos; } } else if (cOvl.HasFlag(Trivalent.Changed)) { Console.WriteLine("\tRe-Built"); continue; } } else if (cIso) { PatchManager.Patch patch; if (Patches.patches.TryGetValue(PatchManager.ToHash(name), out patch) && patch.IsinISO) { Console.WriteLine("\tPatching..."); file.RecordingDate = DateTime.UtcNow; niso.AddFile2(file, patch.Stream, name); continue; } } Console.WriteLine(""); niso.CopyFile(file); if (niso.SectorCount >= 0x230540) { WriteWarning( "Warning: This ISO has the size of a dual-layer ISO, but it isn't one. Some\nprograms may take a while to start while they search for the 2nd layer."); } } } } else { using (var iso = new ISOFileReader(isofile)) using (var niso = new ISOCopyWriter(nisofile, iso)) { ConsoleProgress consoleProgress = new ConsoleProgress((long)iso.Count<FileDescriptor>(), "Patching ISO...", ConsoleColor.Green); Trivalent cKh2 = Patches.KH2Changed ? Trivalent.ChangesPending : Trivalent.NoChanges, cOvl = Patches.OVLChanged ? Trivalent.ChangesPending : Trivalent.NoChanges; bool cIso = Patches.ISOChanged; foreach (FileDescriptor file in iso) { if (UISwitch) { consoleProgress.Text = string.Format("Adding [{0}] {1}", "ISO", file.FullName); } else { decimal nmbpercent = (((decimal)consoleProgress.Current / (decimal)consoleProgress.Total) * 100); consoleProgress.Text = string.Format(" [{0}% Done]", (int)nmbpercent); } consoleProgress.Increment(1L); string name = file.FileName; if (name.EndsWith("KH2.IDX") || name.EndsWith("KH2.IMG")) { if (cKh2.HasFlag(Trivalent.ChangesPending)) { cKh2 = Trivalent.Changed; long lpos = niso.file.Position; try { FileDescriptor img = iso.FindFile("KH2.IMG"), idx = iso.FindFile("KH2.IDX"); using ( MemoryStream ms = PatchIDX(iso.GetFileStream(idx), iso.GetFileStream(img), img, niso, consoleProgress, false) ) { idx.RecordingDate = DateTime.UtcNow; niso.AddFile2(idx, ms, name); } continue; } catch (Exception e) { WriteError(" Error creating IDX/IMG: {0}\n{1}", e.Message, e.StackTrace); niso.file.Position = lpos; } } else if (cKh2.HasFlag(Trivalent.Changed)) { continue; } } else if (name.EndsWith("OVL.IDX") || name.EndsWith("OVL.IMG")) { if (cOvl.HasFlag(Trivalent.ChangesPending)) { cOvl = Trivalent.Changed; long lpos = niso.file.Position; try { FileDescriptor img = iso.FindFile("OVL.IMG"), idx = iso.FindFile("OVL.IDX"); using ( MemoryStream ms = PatchIDX(iso.GetFileStream(idx), iso.GetFileStream(img), img, niso, consoleProgress, true )) { idx.RecordingDate = DateTime.UtcNow; niso.AddFile2(idx, ms, name); } continue; } catch (Exception e) { WriteError(" Error creating IDX/IMG: " + e.Message); niso.file.Position = lpos; } } else if (cOvl.HasFlag(Trivalent.Changed)) { continue; } } else if (cIso) { PatchManager.Patch patch; if (Patches.patches.TryGetValue(PatchManager.ToHash(name), out patch) && patch.IsinISO) { file.RecordingDate = DateTime.UtcNow; niso.AddFile2(file, patch.Stream, name); continue; } } niso.CopyFile(file); if (niso.SectorCount >= 0x230540) { WriteWarning( "Warning: This ISO has the size of a dual-layer ISO, but it isn't one. Some\nprograms may take a while to start while they search for the 2nd layer."); } } consoleProgress.Text = "Done patching."; consoleProgress.Finish(); } } }