/// <summary>Read a file from the ISO</summary> /// <param name="entry">IDX entry describing the file</param> /// <returns>Byte array of the file</returns> /// <exception cref="System.Exception">Thrown when file is too large</exception> public byte[] readFile(IDXEntry entry) { if (entry.size > 0x7FFFFFFF) { throw new Exception("File too large to read"); } iso.Position = dataOffset + (2048 * entry.LBA); return(br.ReadBytes((int)entry.size)); }
/// <summary>Copy file from <c>origISO</c> to <c>iso</c></summary> /// <param name="hash">Hash of filename</param> /// <exception cref="System.Exception">Thrown when no matching hash is found in <c>origISO</c></exception> public void copyFile(UInt32 hash) { IDXEntry entry = origISO.idxEntries.Find(a => a.hash == hash); if (entry == null) { throw new Exception("Failed to find IDX entry in original ISO"); } copyFile(entry); }
/// <summary>Relinks one file to another, so they share the same data</summary> /// <param name="sHash">Source file; What to relink</param> /// <param name="tHash">Target file; What to relink to</param> /// <returns>True if the relink is done, False if it was queued</returns> public bool addRelink(UInt32 sHash, UInt32 tHash) { IDXEntry t = idxEntries.Find(a => a.hash == tHash); if (t != null) { idxEntries.Add(new IDXEntry(sHash, t.flags, t.LBA, t.size)); return(true); } idxRelinks.Add(sHash, tHash); return(false); }
/// <summary>Copy file from <c>origISO</c> to <c>iso</c></summary> /// <param name="entry">IDX entry describing the file in <c>origISO</c></param> /// <exception cref="System.ObjectDisposedException">Thrown when ISO has been finalized</exception> /// <exception cref="System.Exception">Thrown when <c>origISO</c> isn't set</exception> /// <exception cref="System.Exception">Thrown when <c>entry</c> isn't in <c>origISO</c></exception> public void copyFile(IDXEntry entry) { if (finalized) { throw new ObjectDisposedException("ISO has been finalized"); } if (origISO == null) { throw new Exception("No original ISO to copy from"); } if (!origISO.idxEntries.Contains(entry)) { throw new Exception("IDX entry not in original ISO"); } long pos = iso.Position, padding = (entry.size % 2048) == 0 ? 0 : (2048 - (entry.size % 2048)); idxEntries.Add(new IDXEntry(entry.hash, entry.flags, (UInt32)(pos - dataOffset) / 2048, entry.size)); copyBytes(entry.size + padding, origISO.dataOffset + entry.LBA * 2048); updateISOFileInfo(entry.hash, pos, entry.size); }
private static void ExtractIDX(KH1ISOReader input, string tfolder = "export/") { for (int i = 0, idxC = input.idxEntries.Count; i < idxC; ++i) { IDXEntry entry = input.idxEntries[i]; bool compressed = entry.flags == 1; string name2; if (!HashList.pairs.TryGetValue(entry.hash, out name2)) { name2 = String.Format("@noname/{0:x8}.bin", entry.hash); } if (name2 == "system.cnf") { continue; } if (name2 == "SLPS_251.98") { continue; } if (name2 == "ioprp250.img") { continue; } if (name2 == "sio2man.irx") { continue; } if (name2 == "sio2d.irx") { continue; } if (name2 == "dbcman.irx") { continue; } if (name2 == "ds2o.irx") { continue; } if (name2 == "mcman.irx") { continue; } if (name2 == "mcserv.irx") { continue; } if (name2 == "libsd.irx") { continue; } if (name2 == "libssl.irx") { continue; } if (name2 == "dev9.irx") { continue; } if (name2 == "atad.irx") { continue; } if (name2 == "hdd.irx") { continue; } if (name2 == "pfs.irx") { continue; } if (name2 == "kingdom.idx") { continue; } if (name2 == "kingdom.img") { continue; } var idxs = new List <Tuple <IDXFile, string> >(); if (_advanced) { Console.WriteLine("-----------File {0,4}/{1}, using KINGDOM.IDX\n", i, input.idxEntries.Count - 1); Console.WriteLine("Hashed filename: {0}", entry.hash); Console.WriteLine("Compression flags: {0}", compressed); Console.WriteLine("Size (packed): {0}", entry.size); Console.WriteLine("Real name: {0}", name2); } else { Console.WriteLine("[KINGDOM: {0,4}/{1}]\tExtracting {2}", i, input.idxEntries.Count - 1, name2); } string filename = tfolder + "/KINGDOM/" + name2; Directory.CreateDirectory(Path.GetDirectoryName(filename)); bool adSize = _advanced; byte[] file = input.readFile(entry); if (compressed) { if (entry.size > int.MaxValue) { throw new NotSupportedException("File to big to decompress"); } try { byte[] decompressed = KH1Compressor.decompress(file, adSize); File.WriteAllBytes(filename, decompressed); } catch (Exception e) { WriteError(" ERROR: Failed to decompress: " + e.Message); } } else { File.WriteAllBytes(filename, file); } } }
private static void PatchISO(KH1ISOReader input, KH1ISOWriter output, PatchManager files, bool ocompress, string oextHead) { int number = 1; output.writeHeader(oextHead);//Let's copy the header //Console.WriteLine("Adding header using {0} source", ? "external" : "internal");//TODO: Delete this Console.WriteLine for (int i = 0, idxC = input.idxEntries.Count; i < idxC; ++i) { IDXEntry entry = input.idxEntries[i]; if (entry.hash == 0x0392ebe4) { continue; } //kingdom.img if (entry.hash == 0x0393eba4) //kingdom.idx { Console.WriteLine("[KINGDOM: {0}/{1}]\tKINGDOM.IDX", number, input.idxEntries.Count - 1); //-1 'cause of the file KINGDOM.IMG number++; output.writeDummyIDX(idxC); continue; } //Loading the patch UInt32 flags = 0; PatchManager.Patch patch; Stream s = null; uint h = 0; // 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(entry.hash, out patch) && /*patch.Parent == parenthash*/ !patch.IsinISO) { s = patch.Stream; h = patch.Hash; } string name; if (!HashList.pairs.TryGetValue(entry.hash, out name)) { name = String.Format("@noname/{0:x8}.bin", entry.hash); } if (s == null) { flags = entry.flags;//FLAGS NEEDS TO BE OR 0 IF NOTHING, OR 1 IF COMPRESSED, OR THE NAME TO RELINK TO IF IT NEEDS TO if (h != 0) { if (patch.Compressed) { flags = 1; } else if (patch.IsRelink) { flags = patch.Relink; } } if (flags > 1) { Console.WriteLine("[KINGDOM: {0}/{1}]\t{2}\tRelinking...", number, input.idxEntries.Count - 1, name); //-1 'cause of the file KINGDOM.IMG number++; /*if (!HashList.pairs.TryGetValue(flags, out name)) * { * name = String.Format("@noname/{0:x8}.bin", flags); * } * Console.WriteLine("{0}", name);*///Err...what is this crappy code? No but srsly output.addRelink(entry.hash, flags); } else { Console.WriteLine("[KINGDOM: {0}/{1}]\t{2}", number, input.idxEntries.Count - 1, name); //-1 'cause of the file KINGDOM.IMG number++; output.copyFile(entry); } } else { Console.WriteLine("[KINGDOM: {0}/{1}]\t{2}\tPatching...", number, input.idxEntries.Count - 1, name); //-1 'cause of the file KINGDOM.IMG number++; output.importFile(s, entry.hash, flags); } } output.finalize(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("New ISO finished!"); Console.ResetColor(); }
/// <summary>Write the IDX to the ISO, update a few final ISO 9660 values, and Dispose of self</summary> /// <exception cref="System.ObjectDisposedException">Thrown when ISO has already been finalized</exception> /// <exception cref="System.NotSupportedException">Thrown when no IDX dummy has been written</exception> /// <exception cref="System.NotSupportedException"> /// Thrown when there are more IDX entries to write then space was reserved /// for /// </exception> public void finalize() { if (finalized) { throw new ObjectDisposedException("ISO has been finalized"); } else if (idxOffset == 0) { throw new NotSupportedException("No IDX to finalize"); } else if ((idxEntries.Count + idxRelinks.Count) * 16 > idxSize) { throw new NotSupportedException("Trying to write more entries then space was allocated for"); } // Add delayed relinks foreach (var item in idxRelinks) { IDXEntry t = idxEntries.Find((IDXEntry a) => a.hash == item.Value); if (t.hash == item.Value) { idxEntries.Add(new IDXEntry(item.Key, t.flags, t.LBA, t.size)); } else { Console.WriteLine("WARNING: Failed to relink {0:X8} to {1:X8}!", item.Key, item.Value); } } idxRelinks.Clear(); // Sort IDXs by hash idxEntries.Sort((a, b) => a.hash < b.hash ? -1 : (a.hash > b.hash ? 1 : 0)); // Write IDXs iso.Position = idxOffset; var IMGLen = (UInt32)((headerIMGEnd > 0 ? headerIMGEnd : iso.Length) - headerIMGoffset); foreach (IDXEntry entry in idxEntries) { bw.Write(entry.hash); bw.Write(entry.flags); bw.Write(entry.LBA); if (entry.hash == 0x0392ebe4) //kingdom.img needs length saved { bw.Write(IMGLen); } else { bw.Write(entry.size); } } idxEntries.Clear(); if (updateISOHeaders) { UInt32 fileLBA = (UInt32)(iso.Length / 2048), UDFLBA = fileLBA - 263; iso.Position = 32848; bw.Write(_ISO9660Number(fileLBA)); /*ISO9660 Volume Space*/ iso.Position = 69824; bw.Write(UDFLBA); /*UDF Partition size*/ iso.Position = 102592; bw.Write(UDFLBA); /*UDF Partition size (Reserve header)*/ if ((headerFlags & 0x01) != 0) { iso.Position = 535568 + 8; bw.Write(_ISO9660Number(IMGLen)); /*IMG Size*/ } } Console.Write("Flushing data to disk..."); bw.Flush(); if (!NativeMethods.FlushFileBuffers(iso.SafeFileHandle)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Win32 FlushFileBuffers returned error in KH1ISOWriter"); } Console.WriteLine(" Done!"); finalized = true; Dispose(); }
/// <summary>Copy file from <c>origISO</c> to <c>iso</c></summary> /// <param name="entry">IDX entry describing the file in <c>origISO</c></param> /// <exception cref="System.ObjectDisposedException">Thrown when ISO has been finalized</exception> /// <exception cref="System.Exception">Thrown when <c>origISO</c> isn't set</exception> /// <exception cref="System.Exception">Thrown when <c>entry</c> isn't in <c>origISO</c></exception> public void copyFile(IDXEntry entry) { if (finalized) { throw new ObjectDisposedException("ISO has been finalized"); } if (origISO == null) { throw new Exception("No original ISO to copy from"); } if (!origISO.idxEntries.Contains(entry)) { throw new Exception("IDX entry not in original ISO"); } long pos = iso.Position, padding = (entry.size%2048) == 0 ? 0 : (2048 - (entry.size%2048)); idxEntries.Add(new IDXEntry(entry.hash, entry.flags, (UInt32) (pos - dataOffset)/2048, entry.size)); copyBytes(entry.size + padding, origISO.dataOffset + entry.LBA*2048); updateISOFileInfo(entry.hash, pos, entry.size); }
/// <summary>Read a file from the ISO</summary> /// <param name="entry">IDX entry describing the file</param> /// <returns>Byte array of the file</returns> /// <exception cref="System.Exception">Thrown when file is too large</exception> public byte[] readFile(IDXEntry entry) { if (entry.size > 0x7FFFFFFF) { throw new Exception("File too large to read"); } iso.Position = dataOffset + (2048*entry.LBA); return br.ReadBytes((int) entry.size); }