public static ExtractedFile Extract(BND4 bndfile, int ID, string filePath) { var file = new ExtractedFile(bndfile.Files.First(f => f.ID == ID), filePath); System.IO.File.WriteAllBytes(file.Path, file.File.Bytes); return(file); }
public IExtractedFile ExtractDat() { var length = ExtractedFile.GetIntAtOffset(0); var gpt1Length = ExtractedFile.GetIntAtOffset(8); var startOffset = Start; if (gpt1Length > 0 && ExtractedFile.GetIntAtOffset(Start) == GPT1MagicNumber) /*GPT1 magic*/ { startOffset += gpt1Length + 4; } var fileName = FileName.RemoveFileExtensions() + ".dat"; var datFile = $"{Path}/{fileName}".GetNewStream(); ExtractedFile.CopySubStream(datFile, startOffset, length); datFile.Flush(); return(new DAT { FileName = fileName, Path = Path, FileType = FileTypes.DAT, ExtractedFile = datFile }); }
public DOL(string pathToExtractDirectory, ISOExtractor extractor) { Path = pathToExtractDirectory; var fileName = $"{Path}/{FileName}"; ExtractedFile = fileName.GetNewStream(); Offset = (int)extractor.ISOStream.GetUIntAtOffset(DOLStartOffsetLocation); var size = DolHeaderSize; for (int i = 0; i < DolSectionSizesCount; i++) { var offset = Offset + (i * 4) + DolSectionSizesStart; size += (int)extractor.ISOStream.GetUIntAtOffset(offset); } Size = size; if (Configuration.Verbose) { Console.WriteLine($"DOL Size: {Size:X}"); } extractor.ISOStream.CopySubStream(ExtractedFile, Offset, Size); ExtractedFile.Flush(); }
public override Stream Encode(bool isCompressed) { Stream entryStream; ExtractedFile.Seek(0, SeekOrigin.Begin); if (isCompressed) { var tempStream = $"{Path}/{FileName}.lzss".GetNewStream(); ExtractedFile.CopyTo(tempStream); tempStream.Flush(); tempStream.Seek(0, SeekOrigin.Begin); var encoder = new LZSSEncoder(); entryStream = encoder.Encode(tempStream); } else { entryStream = $"{Path}/{FileName}.lzss".GetNewStream(); ExtractedFile.CopyTo(entryStream); } entryStream.AlignStream(0x10); entryStream.Flush(); entryStream.Seek(0, SeekOrigin.Begin); return(entryStream); }
public void ReplacePointer(int index, int newValue) { var pointerStart1 = GetPointerOffset(index); var pointerStart2 = (uint)(firstPointer + (index * RELSizeOfPointer) + RELPointerDataPointer2Offset); ExtractedFile.WriteBytesAtOffset(pointerStart1, ((uint)(newValue - dataStart)).GetBytes()); ExtractedFile.WriteBytesAtOffset(pointerStart2, ((uint)(newValue - dataStart)).GetBytes()); ExtractedFile.Flush(); }
public override Stream Encode(bool _ = false) { var streamCopy = new MemoryStream(); ExtractedFile.Seek(0, SeekOrigin.Begin); ExtractedFile.CopyTo(streamCopy); streamCopy.Seek(0, SeekOrigin.Begin); return(streamCopy); }
/// <summary> /// Recreates FST.bin from the current directory state. I.e. recreate the underlying stream. /// </summary> public void RebuildFST() { ExtractedFile.Dispose(); ExtractedFile = $"{Path}/{FileName}".GetNewStream(); var entries = GetFlattenedFST(); // write root dir ExtractedFile.WriteByte(1); ExtractedFile.WriteByte(0); ExtractedFile.WriteByte(0); ExtractedFile.WriteByte(0); ExtractedFile.Write(0.GetBytes()); ExtractedFile.Write((entries.Count + 1).GetBytes()); // instead of seeking back and forth, store name bytes as they come and write it at the end. var nameBytes = new List <byte>(); for (int i = 0; i < entries.Count; i++) { var entry = entries[i]; if (entry is FSTFileEntry fileEntry) { ExtractedFile.Write(fileEntry.NameOffset.GetBytes()); ExtractedFile.Write(fileEntry.FileDataOffset.GetBytes()); ExtractedFile.Write(fileEntry.Size.GetBytes()); } else if (entry is FSTDirectory dir) { var nameOffsetBytes = dir.NameOffset.GetBytes(); nameOffsetBytes[0] = 1; ExtractedFile.Write(nameOffsetBytes); ExtractedFile.Write(dir.ParentEntry.GetBytes()); ExtractedFile.Write(dir.EndEntry.GetBytes()); } var nameByteArray = entry.Name.ToByteArray(); if (nameByteArray.Length > 0) { nameBytes.AddRange(nameByteArray); nameBytes.Add(0); } } ExtractedFile.Write(nameBytes.ToArray()); // fst.bin is aligned to the nearest 4 bytes var m = ExtractedFile.Length % 4; if (m > 0) { ExtractedFile.Write(new byte[4 - m]); } ExtractedFile.Flush(); }
public void AdjustPointerStart(int byAmount) { var newPointerStart = (uint)(ExtractedFile.GetUIntAtOffset(RELPointersStartOffsetLocation) + byAmount); var pointerHeaderStart = ExtractedFile.GetUIntAtOffset(RELPointersHeaderPointer1Offset); var newPointerHeaderStart = (uint)(pointerHeaderStart + byAmount); var newPointerHeaderEnd = (uint)(ExtractedFile.GetUIntAtOffset(pointerHeaderStart + 0xC) + byAmount); ExtractedFile.WriteBytesAtOffset(RELPointersStartOffsetLocation, newPointerStart.GetBytes()); ExtractedFile.WriteBytesAtOffset(RELPointersHeaderPointer1Offset, newPointerHeaderStart.GetBytes()); ExtractedFile.WriteBytesAtOffset(RELPointersHeaderPointer2Offset, newPointerStart.GetBytes()); ExtractedFile.WriteBytesAtOffset(pointerHeaderStart + 0x4, newPointerStart.GetBytes()); ExtractedFile.WriteBytesAtOffset(pointerHeaderStart + 0xC, newPointerHeaderEnd.GetBytes()); firstPointer = newPointerStart + RELPointersFirstPointerOffset; }
void GetOffsets() { var currentOffset = kEndOfHeader; for (int i = 0; i < NumberOfEntries; i++) { var id = ExtractedFile.GetIntAtOffset(currentOffset) & 0xFFFFF; var offset = ExtractedFile.GetIntAtOffset(currentOffset + 4); if (!stringOffsets.ContainsKey(id)) { stringOffsets.Add(id, offset); } currentOffset += 8; } }
public GSWTexture() { FileType = FileTypes.GSW; var numberOfIds = ExtractedFile.GetUShortAtOffset(0x18); metadata = new List <GSWMetadata>(); for (int i = 1; i < numberOfIds && i <= 0xFF; i++) { var search = SearchForID(i); if (search.HasValue) { metadata.Add(search.Value); } } }
public int ExtraChracters() { var currentChar = 0; var currentOffset = (int)ExtractedFile.Length - 3; var length = 0; while (currentChar == 0) { currentChar = ExtractedFile.GetByteAtOffset(currentOffset); if (currentChar == 0) { length++; } currentOffset--; } return(length); }
public void Load() { if (Configuration.Verbose) { Console.WriteLine($"Extracting TOC."); } rootDirectory = new FSTDirectory(0, 0, 0); var numberOfEntries = ExtractedFile.GetIntAtOffset(TOCNumberEntriesOffset); LoadFST(rootDirectory, numberOfEntries); if (Configuration.Verbose) { Console.WriteLine($"Finished reading FST."); } }
void LoadFST(FSTDirectory root, int endEntryIndex, int firstEntryIndex = 1) { int index = firstEntryIndex; while (index < endEntryIndex) { var entryOffset = index * 12; var folder = ExtractedFile.GetByteAtOffset(entryOffset) == 1; FSTEntry fileEntry; uint nameOffset; if (folder) { nameOffset = (ExtractedFile.GetUIntAtOffset(entryOffset) & 0x00FFFFFF); var parentEntry = ExtractedFile.GetIntAtOffset(entryOffset + 4); var endDirEntry = ExtractedFile.GetIntAtOffset(entryOffset + 8); var directory = new FSTDirectory(index, nameOffset, parentEntry); LoadFST(directory, endDirEntry, index + 1); fileEntry = directory; index += endDirEntry - index; } else { nameOffset = ExtractedFile.GetUIntAtOffset(entryOffset); var fileOffset = ExtractedFile.GetUIntAtOffset(entryOffset + 4); var fileSize = ExtractedFile.GetUIntAtOffset(entryOffset + 8); fileEntry = new FSTFileEntry(index, nameOffset, fileOffset, fileSize); index++; if (fileOffset < StartDataOffset) { StartDataOffset = fileOffset; } } if (nameOffset > LastNameOffset) { LastNameOffset = nameOffset; } var fileName = ExtractedFile.GetStringAtOffset(nameOffset + TOCFirstStringOffset); fileEntry.Name = fileName; root.Children.Add(fileEntry); } }
void LoadFileDetails() { for (int i = 0; i < NumberOfEntries; i++) { var start = GetStartOffsetForFileDetails(i); var fileDetails = new FSysDetailsHeader { Identifier = ExtractedFile.GetUShortAtOffset(start), Filetype = (FileTypes)ExtractedFile.GetByteAtOffset(start + FileFormatOffset), StartOffset = ExtractedFile.GetUIntAtOffset(start + FileStartPointerOffset), UncompressedSize = ExtractedFile.GetUIntAtOffset(start + UncompressedSizeOffset), CompressedSize = ExtractedFile.GetUIntAtOffset(start + CompressedSizeOffset), FileFormatIndexOffset = ExtractedFile.GetUIntAtOffset(start + FileFormatIndexOffset), NameOffset = ExtractedFile.GetUIntAtOffset(start + FileDetailsFilenameOffset) }; fileDetails.FileName = ExtractedFile.GetStringAtOffset(fileDetails.NameOffset); fSysDetailsHeaders.Add(fileDetails); } }
public FST(string pathToExtractDirectory, ISOExtractor extractor) { Path = pathToExtractDirectory; FileName = "Game.toc"; ExtractedFile = $"{Path}/{FileName}".GetNewStream(); // load toc Offset = (int)extractor.ISOStream.GetUIntAtOffset(TOCStartOffsetLocation); Size = (int)extractor.ISOStream.GetUIntAtOffset(TOCFileSizeLocation); if (Configuration.Verbose) { Console.WriteLine("Reading TOC from ISO"); Console.WriteLine($"TOC Start: {Offset:X}"); Console.WriteLine($"TOC Length: {Size:X}"); } // write to disk extractor.ISOStream.CopySubStream(ExtractedFile, Offset, Size); ExtractedFile.Flush(); Load(); }
public IEnumerable <Texture> ExtractTextureData() { var textures = new List <Texture>(); foreach (var info in metadata) { var filename = $"{Path}/{FileName.RemoveFileExtensions()}{info.Id}.gtx"; var extractedFile = File.Open(filename, FileMode.Create, FileAccess.ReadWrite); ExtractedFile.CopySubStream(extractedFile, info.StartOffset, info.DataSize); extractedFile.Flush(); var entry = new Texture { Path = Path, FileName = filename, FileType = FileTypes.GTX, ExtractedFile = extractedFile }; textures.Add(entry); } return(textures); }
GSWMetadata?SearchForID(int id) { var headerMarker = new byte[] { 3, 0, 0, (byte)id }; var offsets = ExtractedFile.OccurencesOfBytes(BitConverter.ToInt32(headerMarker)); foreach (var offset in offsets) { if (ExtractedFile.GetUShortAtOffset(offset + 0x24) == 0x0801) { var formatID = ExtractedFile.GetIntAtOffset(offset + 0x28); var palletteSize = ExtractedFile.GetIntAtOffset(offset + 0x68); var textureSize = palletteSize + 0x200; var textureStart = offset + 0x20; return(new GSWMetadata { Id = id, StartOffset = textureSize, DataSize = textureStart }); } } return(null); }
public UnicodeString GetStringAtOffset(int offset) { var currentOffset = offset; var currChar = 0x0; var nextChar = 0x1; var str = new UnicodeString(); while (nextChar != 0) { if (currentOffset + 2 > ExtractedFile.Length) { break; } currChar = ExtractedFile.GetUShortAtOffset(currentOffset); currentOffset += 2; if (currChar == 0xFFFF) { var specChar = (SpecialCharacters)ExtractedFile.GetByteAtOffset(currentOffset); currentOffset += 1; var extra = specChar.ExtraBytes(); var bytes = new byte[extra]; ExtractedFile.Seek(currentOffset, SeekOrigin.Begin); currentOffset += ExtractedFile.Read(bytes); str.Add(new SpecialUnicodeCharacters(specChar, bytes)); } else { str.Add(new UnicodeCharacters(currChar)); } nextChar = ExtractedFile.GetUShortAtOffset(currentOffset); } return(str); }
public uint GetPointer(int index) { var offset = GetPointerOffset(index); return(ExtractedFile.GetUIntAtOffset(offset) + dataStart); }
public uint GetValueAtPointer(int index) { var offset = GetPointer(index); return(ExtractedFile.GetUIntAtOffset(offset)); }
public override Stream Encode(bool _ = false) { Stream fSysStream = $"{Path}/{FileName}.repak".GetNewStream(); if (ExtractedEntries.Count == 0) { // nothing extracted, nothing changed // just copy the existing stream back ExtractedFile.Seek(0, SeekOrigin.Begin); ExtractedFile.CopyTo(fSysStream); return(fSysStream); } // unpack the entire fsys archive for easier repacking if (ExtractedEntries.Count < NumberOfEntries) { FSysExtractor.ExtractFSys(this, false); } // copy the header back, we'll update the sizes later NumberOfEntries = ExtractedEntries.Count; ExtractedFile.Seek(0, SeekOrigin.Begin); ExtractedFile.CopySubStream(fSysStream, 0, 0x60); var sizeOfDetailsPointers = (fSysDetailsHeaders.Count * 4); var startNameOffset = 0x60 + sizeOfDetailsPointers + sizeOfDetailsPointers.GetAlignBytesCount(16); fSysStream.Seek(startNameOffset, SeekOrigin.Begin); // write the name table var startDataOffset = uint.MaxValue; foreach (var detailHeader in fSysDetailsHeaders) { fSysStream.Write(detailHeader.FileName.ToByteArray()); fSysStream.WriteByte(0); if (detailHeader.StartOffset < startDataOffset) { startDataOffset = detailHeader.StartOffset; } } // align names fSysStream.AlignStream(0x10); var lastNameOffset = (int)fSysStream.Position; var startDetailsOffsewt = 0x60; // write pointers to details offset fSysStream.Seek(startDetailsOffsewt, SeekOrigin.Begin); for (int x = 0; x < fSysDetailsHeaders.Count; x++) { fSysStream.Write((lastNameOffset + (x * 0x70)).GetBytes()); } // write our data, update offsets along the way if we find mismatches for (int i = 0; i < fSysDetailsHeaders.Count; i++) { var detailHeader = fSysDetailsHeaders[i]; var entryFileName = detailHeader.FileName.ToString(); if (!entryFileName.EndsWith(detailHeader.Filetype.FileTypeName())) { entryFileName = $"{entryFileName}{detailHeader.Filetype.FileTypeName()}"; } var entry = ExtractedEntries[entryFileName]; using var encodeStream = entry.Encode(detailHeader.IsCompressed); fSysStream.Seek(detailHeader.StartOffset, SeekOrigin.Begin); encodeStream.CopyTo(fSysStream); fSysStream.Flush(); detailHeader.UncompressedSize = (uint)entry.ExtractedFile.Length; if (encodeStream.Length != detailHeader.CompressedSize) { var adjustedSize = (int)(encodeStream.Length - detailHeader.CompressedSize); detailHeader.CompressedSize = (uint)encodeStream.Length; if (adjustedSize < 0) { continue; // probably wasteful, but meh } for (int j = i + 1; j < fSysDetailsHeaders.Count; j++) { var adjDetailsHeader = fSysDetailsHeaders[j]; adjDetailsHeader.StartOffset += (uint)adjustedSize; adjDetailsHeader.StartOffset += adjDetailsHeader.StartOffset.GetAlignBytesCount(0x10); } } } fSysStream.AlignStream(0x10); fSysStream.Write(new byte[0x10]); fSysStream.Seek(-4, SeekOrigin.Current); fSysStream.Write(FSYSbytes.GetBytes()); fSysStream.Flush(); fSysStream.WriteBytesAtOffset(FSYSFileSizeOffset, ((int)fSysStream.Length).GetBytes()); // go back and re-write our file details table fSysStream.Seek(lastNameOffset, SeekOrigin.Begin); foreach (var detailHeader in fSysDetailsHeaders) { fSysStream.Write(detailHeader.Encode()); } fSysStream.Flush(); fSysStream.Seek(0, SeekOrigin.Begin); return(fSysStream); }
public int GetStartOffsetForFileDetails(int index) { return(ExtractedFile.GetIntAtOffset(FirstFileDetailsPointerOffset + (index * 4))); }
public void SetValueAtPointer(int index, int newValue) { var offset = GetPointer(index); ExtractedFile.WriteBytesAtOffset(offset, newValue.GetBytes()); }