private Stream GetIdxStreamWhichContainsTargetedFile(List <Idx.Entry> idxEntries, Stream imgStream, string fileName) { var idxDictionary = new IdxDictionary { idxEntries }; foreach (var innerIdx in Img.InternalIdxs) { if (idxDictionary.TryGetEntry(innerIdx, out var innerIdxEntry)) { var innerIdxStream = OpenIsoSubStream(imgStream, innerIdxEntry.Offset, innerIdxEntry.Length); var innerIdxDictionary = new IdxDictionary { Idx.Read(innerIdxStream) }; if (innerIdxDictionary.Exists(fileName)) { return(innerIdxStream); } } } return(null); }
public void WriteIdxEntry() => Helpers.AssertStream(CreateMockIdxStream(1, 2, 3, 4, 5), stream => { var outStream = new MemoryStream(); Idx.Write(outStream, Idx.Read(stream)); return(outStream); });
private static IEnumerable <Idx.Entry> OpenIdx(string fileName) { using var idxStream = File.OpenRead(fileName); if (!Idx.IsValid(idxStream)) { throw new CustomException($"The IDX {fileName} is invalid or not recognized."); } return(Idx.Read(idxStream)); }
private static IEnumerable <EntryViewModel> GetChildren(string idxName, IIdxManager idxManager) { var idxStream = idxManager.OpenFileFromIdx(idxName); if (idxStream == null) { return(new EntryViewModel[0]); } using (idxStream) { return(EntryParserModel.GetChildren(Idx.Read(idxStream), idxManager)); } }
public static List <Msg.Entry> ReadMsgFromIdx(Stream idxStream, Stream imgStream) { var img = new Img(imgStream, Idx.Read(idxStream), false); foreach (var language in Constants.Regions) { var stream = img.FileOpen($"msg/{language}/sys.bar"); if (stream != null) { return(ReadMsgFromBar(stream)); } } throw new FileNotFoundException($"Unable to find a 'sys.bar' between the supported languages."); }
protected int OnExecute(CommandLineApplication app) { const long EsitmatedMaximumImgFileSize = 4L * 1024 * 1024 * 1024; // 4GB const int EsitmatedMaximumIdxFileSize = 600 * 1024; // 600KB const int EstimatedMaximumIdxEntryAmountToBeValid = EsitmatedMaximumIdxFileSize / 0x10 - 4; using var isoStream = File.Open(InputIso, FileMode.Open, FileAccess.ReadWrite); if (IdxIsoBlock == -1 || ImgIsoBlock == -1) { const int needleLength = 0x0B; var imgNeedle = new byte[needleLength] { 0x01, 0x09, 0x4B, 0x48, 0x32, 0x2E, 0x49, 0x4D, 0x47, 0x3B, 0x31 }; var idxNeedle = new byte[needleLength] { 0x01, 0x09, 0x4B, 0x48, 0x32, 0x2E, 0x49, 0x44, 0x58, 0x3B, 0x31 }; const uint basePosition = 0x105 * 0x800; for (int i = 0; i < 0x500; i++) { isoStream.Position = basePosition + i; var hayRead = isoStream.ReadBytes(needleLength); var idxCmp = hayRead.SequenceEqual(idxNeedle); var imgCmp = hayRead.SequenceEqual(imgNeedle); if (imgCmp || idxCmp) { isoStream.Position -= 0x24; var blockStack = isoStream.ReadBytes(0x04); var blockCorrect = new byte[0x04] { blockStack[3], blockStack[2], blockStack[1], blockStack[0] }; if (idxCmp && IdxIsoBlock == -1) { IdxIsoBlock = BitConverter.ToInt32(blockCorrect); } else if (imgCmp && ImgIsoBlock == -1) { ImgIsoBlock = BitConverter.ToInt32(blockCorrect); } } } if (IdxIsoBlock == -1 || ImgIsoBlock == -1) { throw new IOException("Could not determine the LBA Offsets of KH2.IDX or KH2.IMG, is this ISO valid?"); } } var idxStream = OpenIsoSubStream(isoStream, IdxIsoBlock, EsitmatedMaximumIdxFileSize); using var imgStream = OpenIsoSubStream(isoStream, ImgIsoBlock, EsitmatedMaximumImgFileSize); var idxEntryCount = idxStream.ReadInt32(); if (idxEntryCount > EstimatedMaximumIdxEntryAmountToBeValid) { throw new CustomException("There is a high chance that the IDX block is not valid, therefore the injection will terminate to avoid corruption."); } var idxEntries = Idx.Read(idxStream.SetPosition(0)); var entry = idxEntries.FirstOrDefault(x => x.Hash32 == Idx.GetHash32(FilePath) && x.Hash16 == Idx.GetHash16(FilePath)); if (entry == null) { idxStream = GetIdxStreamWhichContainsTargetedFile(idxEntries, imgStream, FilePath); if (idxStream == null) { throw new CustomException($"The file {FilePath} has not been found inside the KH2.IDX, therefore the injection will terminate."); } idxEntries = Idx.Read(idxStream.SetPosition(0)); entry = idxEntries.FirstOrDefault(x => x.Hash32 == Idx.GetHash32(FilePath) && x.Hash16 == Idx.GetHash16(FilePath)); } var inputData = File.ReadAllBytes(InputFile); var decompressedLength = inputData.Length; if (Uncompressed == false) { inputData = Img.Compress(inputData); } var blockCountRequired = (inputData.Length + 0x7ff) / 0x800 - 1; if (blockCountRequired > entry.BlockLength) { throw new CustomException($"The file to inject is too big: the actual is {inputData.Length} but the maximum allowed is {GetLength(entry.BlockLength)}."); } imgStream.SetPosition(GetOffset(entry.Offset)); // Clean completely the content of the previous file to not mess up the decompression imgStream.Write(new byte[GetLength(entry.BlockLength)]); imgStream.SetPosition(GetOffset(entry.Offset)); imgStream.Write(inputData); entry.IsCompressed = !Uncompressed; entry.Length = decompressedLength; // we are intentionally not patching entry.BlockLength because it would not allow to insert back bigger files. Idx.Write(idxStream.SetPosition(0), idxEntries); return(0); }
protected int OnExecute(CommandLineApplication app) { const long EsitmatedMaximumImgFileSize = 4L * 1024 * 1024 * 1024; // 4GB const int EsitmatedMaximumIdxFileSize = 600 * 1024; // 600KB const int EstimatedMaximumIdxEntryAmountToBeValid = EsitmatedMaximumIdxFileSize / 0x10 - 4; using var isoStream = File.Open(InputIso, FileMode.Open, FileAccess.ReadWrite); if (IdxIsoBlock == -1 || ImgIsoBlock == -1) { var bufferedStream = new BufferedStream(isoStream); IdxIsoBlock = IsoUtility.GetFileOffset(bufferedStream, "KH2.IDX;1"); ImgIsoBlock = IsoUtility.GetFileOffset(bufferedStream, "KH2.IMG;1"); if (IdxIsoBlock == -1 || ImgIsoBlock == -1) { throw new IOException("Could not determine the LBA Offsets of KH2.IDX or KH2.IMG, is this ISO valid?"); } } var idxStream = OpenIsoSubStream(isoStream, IdxIsoBlock, EsitmatedMaximumIdxFileSize); using var imgStream = OpenIsoSubStream(isoStream, ImgIsoBlock, EsitmatedMaximumImgFileSize); var idxEntryCount = idxStream.ReadInt32(); if (idxEntryCount > EstimatedMaximumIdxEntryAmountToBeValid) { throw new CustomException("There is a high chance that the IDX block is not valid, therefore the injection will terminate to avoid corruption."); } var idxEntries = Idx.Read(idxStream.SetPosition(0)); var entry = idxEntries.FirstOrDefault(x => x.Hash32 == Idx.GetHash32(FilePath) && x.Hash16 == Idx.GetHash16(FilePath)); if (entry == null) { idxStream = GetIdxStreamWhichContainsTargetedFile(idxEntries, imgStream, FilePath); if (idxStream == null) { throw new CustomException($"The file {FilePath} has not been found inside the KH2.IDX, therefore the injection will terminate."); } idxEntries = Idx.Read(idxStream.SetPosition(0)); entry = idxEntries.FirstOrDefault(x => x.Hash32 == Idx.GetHash32(FilePath) && x.Hash16 == Idx.GetHash16(FilePath)); } var inputData = File.ReadAllBytes(InputFile); var decompressedLength = inputData.Length; if (Uncompressed == false) { inputData = Img.Compress(inputData); } var blockCountRequired = (inputData.Length + 0x7ff) / 0x800 - 1; if (blockCountRequired > entry.BlockLength) { throw new CustomException($"The file to inject is too big: the actual is {inputData.Length} but the maximum allowed is {GetLength(entry.BlockLength)}."); } imgStream.SetPosition(GetOffset(entry.Offset)); // Clean completely the content of the previous file to not mess up the decompression imgStream.Write(new byte[GetLength(entry.BlockLength)]); imgStream.SetPosition(GetOffset(entry.Offset)); imgStream.Write(inputData); entry.IsCompressed = !Uncompressed; entry.Length = decompressedLength; // we are intentionally not patching entry.BlockLength because it would not allow to insert back bigger files. Idx.Write(idxStream.SetPosition(0), idxEntries); return(0); }
private static Idx OpenIdx(string fileName) { using (var idxStream = File.OpenRead(fileName)) return(Idx.Read(idxStream)); }
public IdxDataContent(Stream idxStream, Stream imgStream) { _idx = Idx.Read(idxStream); _img = new Img(imgStream, _idx, false); }