public void Seeking_OperateCorrectly() { var data = new byte[] { 1, 2, 3, 24, 1, 3, 24, 1, 3, 8, 3, 5, 7 }; var subStream = new SubStream(new MemoryStream(data) { Position = 0 }, 2, 9); MemoryStream ouputStream = new MemoryStream(); subStream.CopyTo(ouputStream); Assert.AreEqual(subStream.Length, subStream.Position); CollectionAssert.AreEqual( data.Skip(2).Take(9).ToArray(), ouputStream.ToArray()); subStream.Position = 4; ouputStream = new MemoryStream(); subStream.CopyTo(ouputStream); CollectionAssert.AreEqual( data.Skip(2 + 4).Take(9 - 4).ToArray(), ouputStream.ToArray()); }
private (IList <short>, Stream) SplitTiles(byte[] imageData, int bitDepth) { var tileSize = _tileEntrySize * bitDepth / 8; var result = new MemoryStream(); var tiles = new short[imageData.Length / tileSize]; var tileDictionary = new Dictionary <uint, int>(); var crc32 = Crc32.Create(Crc32Formula.Normal); var offset = 0; var tileIndex = 0; for (var i = 0; i < imageData.Length / tileSize; i++) { var tileStream = new SubStream(new MemoryStream(imageData), offset, tileSize); var hash = BinaryPrimitives.ReadUInt32BigEndian(crc32.Compute(tileStream)); if (!tileDictionary.ContainsKey(hash)) { tileDictionary[hash] = tileIndex++; tileStream.Position = 0; tileStream.CopyTo(result); } tiles[i] = (short)tileDictionary[hash]; offset += tileSize; } return(tiles, result); }
/// <summary> /// Locate and load the encrypted FAT data into memory /// </summary> /// <returns>Returns true on success</returns> public bool LoadRawFAT() { // Read all File Table Data into Memory FAT.SetLength(0); long TotalFileInfoSize = (fileCount + extraFileCount) * fileInfoSize; _owner._gpFileStream.Seek(0, SeekOrigin.End); FirstFileInfoOffset = _owner._gpFileStream.Position; // Search for the first file location, it needs to be alligned to a 0x200 size block FirstFileInfoOffset -= headerSize; FirstFileInfoOffset -= TotalFileInfoSize; var dif = FirstFileInfoOffset % 0x200; // Align to previous block of 512 bytes FirstFileInfoOffset -= dif; _owner._gpFileStream.Position = FirstFileInfoOffset; SubStream _fat = new SubStream(_owner._gpFileStream, FirstFileInfoOffset, _owner._gpFileStream.Length - FirstFileInfoOffset); _fat.CopyTo(FAT); return(true); }
private (Stream imageData, Stream tileData) SplitTiles(Stream image, int bitDepth) { var tileByteDepth = 64 * bitDepth / 8; var tileTable = new MemoryStream(); var imageData = new MemoryStream(); using var tileBw = new BinaryWriterX(tileTable, true); using var imageBw = new BinaryWriterX(imageData, true); if (_tileTableLegacyStart != null) { tileTable.Write(_tileTableLegacyStart, 0, _tileTableLegacyStart.Length); } var crc32 = Crc32.Create(Crc32Formula.Normal); var tileDictionary = new Dictionary <uint, int>(); // Add placeholder tile for all 0's var zeroTileHash = ToUInt32BigEndian(crc32.Compute(new byte[tileByteDepth])); tileDictionary[zeroTileHash] = -1; var imageOffset = 0; var tileIndex = 0; while (imageOffset < image.Length) { var tile = new SubStream(image, imageOffset, tileByteDepth); var tileHash = ToUInt32BigEndian(crc32.Compute(tile)); if (!tileDictionary.ContainsKey(tileHash)) { tile.Position = 0; tile.CopyTo(imageBw.BaseStream); tileDictionary[tileHash] = tileIndex++; } if (_tileTableLegacyStart != null) { tileBw.Write(tileDictionary[tileHash]); } else { tileBw.Write((short)tileDictionary[tileHash]); } imageOffset += tileByteDepth; } imageData.Position = tileTable.Position = 0; return(imageData, tileTable); }
private static void Main(string[] args) { try { Dictionary <string, RS5DirectoryEntry> directory = OpenRS5Files(); Console.Write("Processing environment ... "); SubStream environdata = directory["environment"].Data.Chunks["DATA"].Data; using (Stream environfile = File.Create("environment.bin")) { environdata.CopyTo(environfile); } RS5Environment environ = new RS5Environment(environdata); Dictionary <string, List <AnimationClip> > animclips = ProcessEnvironmentAnimations(environ); Console.WriteLine("Done"); XElement environ_xml = environ.ToXML(); try { environ_xml.Save("environment.xml"); WriteRS5Contents(directory, animclips); } catch (UnauthorizedAccessException) { System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); string exepath = Path.GetDirectoryName(asm.Location); Console.WriteLine("Unable to write to working directory {0}", Environment.CurrentDirectory); Console.WriteLine("Do you want to write to the directory the executable is in?"); Console.WriteLine("({0})", exepath); Console.Write("[y/N] "); ConsoleKeyInfo keyinfo = Console.ReadKey(false); Console.WriteLine(); if (keyinfo.KeyChar == 'y' || keyinfo.KeyChar == 'Y') { Environment.CurrentDirectory = exepath; environ_xml.Save("environment.xml"); WriteRS5Contents(directory, animclips); } } } catch (FileNotFoundException) { Console.WriteLine("Unable to load RS5 files"); } catch (Exception ex) { Console.Error.WriteLine("Caught exception: {0}\n\nPlease report this to Ben Peddell <*****@*****.**>", ex.ToString()); } Console.Error.Write("Press any key to exit"); Console.ReadKey(true); }
public void SubStream_ReturnsSubSectionOfInnerStreamData(byte[] data, int offset, int amount) { var subStream = new SubStream(new MemoryStream(data) { Position = 0 }, offset, amount); Assert.AreEqual(0, subStream.Position); Assert.AreEqual(amount, subStream.Length); MemoryStream ouputStream = new MemoryStream(); subStream.CopyTo(ouputStream); Assert.AreEqual(subStream.Length, subStream.Position); CollectionAssert.AreEqual( data.Skip(offset).Take(amount).ToArray(), ouputStream.ToArray()); }
private (Stream imageData, Stream tileData) SplitTiles(Stream image, int bitDepth) { var tileByteDepth = 64 * bitDepth / 8; var tileTable = new MemoryStream(); var imageData = new MemoryStream(); using var tileBw = new BinaryWriterX(tileTable, true); using var imageBw = new BinaryWriterX(imageData, true); var crc32 = Crc32.Default; var tileDictionary = new Dictionary <uint, short>(); // Add placeholder tile for all 0's var zeroTileHash = crc32.ComputeValue(new byte[tileByteDepth]); tileDictionary[zeroTileHash] = -1; var imageOffset = 0; var tileIndex = 0; while (imageOffset < image.Length) { var tile = new SubStream(image, imageOffset, tileByteDepth); var tileHash = crc32.ComputeValue(tile); if (!tileDictionary.ContainsKey(tileHash)) { tile.Position = 0; tile.CopyTo(imageBw.BaseStream); tileDictionary[tileHash] = (short)tileIndex++; } tileBw.Write(tileDictionary[tileHash]); imageOffset += tileByteDepth; } imageData.Position = tileTable.Position = 0; return(imageData, tileTable); }
static void Main(string[] args) { #if !DEBUG if (args.Length < 1) { Console.WriteLine("FARC Pack"); Console.WriteLine("========="); Console.WriteLine("Packer/unpacker for .FARC files.\n"); Console.WriteLine("Usage:"); Console.WriteLine(" FarcPack [options] [source] [destination]"); Console.WriteLine(" Source can be either FARC or directory."); Console.WriteLine(" Destination can be left empty.\n"); Console.WriteLine("Options:"); Console.WriteLine(" -a, -alignment Set alignment for output FARC."); Console.WriteLine(" 16 by default.\n"); Console.WriteLine(" -c, --compress Compress files in output FARC."); Console.WriteLine(" Disabled by default."); Console.ReadLine(); return; } #endif string sourcePath = null; string destinationPath = null; bool compress = false; uint alignment = 16; for (int i = 0; i < args.Length; i++) { string arg = args[i]; Func <string, string, bool> compare = (a, b) => arg.Equals(a, StringComparison.OrdinalIgnoreCase) || arg.Equals(b, StringComparison.OrdinalIgnoreCase); alignment = compare("-a", "-alignment") ? uint.Parse(args[++i]) : alignment; compress = compare("-c", "-compress") || compress; if (sourcePath == null && !compare("-c", "-compress") && !compare("-a", "-alignment")) { sourcePath = arg; } else if (destinationPath == null && !compare("-c", "-compress") && !compare("-a", "-alignment")) { destinationPath = arg; } } #if DEBUG sourcePath = @"C:\Users\waelw.WAELS-PC\Desktop\farc\vr_cmn"; #endif if (sourcePath == null) { throw new ArgumentException("You must provide a source.", nameof(sourcePath)); } var serial = new BinarySerializer(); if (sourcePath.EndsWith(".farc", StringComparison.OrdinalIgnoreCase)) { destinationPath = destinationPath ?? Path.ChangeExtension(sourcePath, null); #if USE_NEW var archive = new FarcArchiveBin(); using (var file = File.Open(sourcePath, FileMode.Open)) { archive = serial.Deserialize <FarcArchiveBin>(file); archive.Unpack(destinationPath); } #else var archive = new FarcArchive(); archive.Load(sourcePath); using (Stream source = File.OpenRead(sourcePath)) { foreach (var entry in archive) { using (Stream entrySource = new SubStream(source, entry.Position, entry.Length)) using (Stream destination = File.Create(Path.Combine(destinationPath, entry.FileName))) { if (archive.IsEncrypted) { using (AesManaged aes = new AesManaged { KeySize = 128, Key = FarcArchive.FarcEncryptionKeyBytes, BlockSize = 128, Mode = CipherMode.ECB, Padding = PaddingMode.Zeros, IV = new byte[16], }) using (CryptoStream cryptoStream = new CryptoStream( entrySource, aes.CreateDecryptor(), CryptoStreamMode.Read)) { if (archive.IsCompressed && entry.Length != entry.CompressedLength) { using (GZipStream gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) { gzipStream.CopyTo(destination); } } else { cryptoStream.CopyTo(destination); } } } else if (archive.IsCompressed && entry.Length != entry.CompressedLength) { using (GZipStream gzipStream = new GZipStream(entrySource, CompressionMode.Decompress)) { gzipStream.CopyTo(destination); } } else { entrySource.CopyTo(destination); } } } } #endif } else if (File.GetAttributes(sourcePath).HasFlag(FileAttributes.Directory)) { #if USE_NEW var archive = new FarcArchiveBin(); archive.Alignment = (int)alignment; #else var archive = new FarcArchive(); archive.Alignment = alignment; #endif archive.IsCompressed = compress; #if DEBUG archive.Alignment = 64; #endif destinationPath = destinationPath ?? sourcePath + ".farc"; foreach (string fileName in Directory.GetFiles(sourcePath)) { #if USE_NEW archive.Add(new FarcEntryBin(fileName)); #else archive.Add(new FarcEntry { FileName = Path.GetFileName(fileName), FilePath = new FileInfo(fileName) }); #endif } #if USE_NEW archive.Flush(); using (var save = File.Create(destinationPath)) { serial.Serialize(save, archive); } #else archive.Save(destinationPath); #endif } }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("FARC Pack"); Console.WriteLine("========="); Console.WriteLine("Packer/unpacker for .FARC files.\n"); Console.WriteLine("Usage:"); Console.WriteLine(" FarcPack [options] [source] [destination]"); Console.WriteLine(" Source can be either FARC or directory."); Console.WriteLine(" Destination can be left empty.\n"); Console.WriteLine("Options:"); Console.WriteLine(" -a, -alignment Set alignment for output FARC."); Console.WriteLine(" 16 by default.\n"); Console.WriteLine(" -c, --compress Compress files in output FARC."); Console.WriteLine(" Disabled by default."); Console.ReadLine(); return; } string sourcePath = null; string destinationPath = null; bool compress = false; uint alignment = 16; for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.Equals("-a", StringComparison.OrdinalIgnoreCase) || arg.Equals("-alignment", StringComparison.OrdinalIgnoreCase)) { alignment = uint.Parse(args[++i]); } else if (arg.Equals("-c", StringComparison.OrdinalIgnoreCase) || arg.Equals("-compress", StringComparison.OrdinalIgnoreCase)) { compress = true; } else if (sourcePath == null) { sourcePath = arg; } else if (destinationPath == null) { destinationPath = arg; } } if (sourcePath == null) { throw new ArgumentException("You must provide a source.", nameof(sourcePath)); } if (sourcePath.EndsWith(".farc", StringComparison.OrdinalIgnoreCase)) { FarcArchive archive = new FarcArchive(); archive.Load(sourcePath); if (destinationPath == null) { destinationPath = Path.ChangeExtension(sourcePath, null); } Directory.CreateDirectory(destinationPath); using (Stream source = File.OpenRead(sourcePath)) { foreach (FarcEntry entry in archive) { using (Stream entrySource = new SubStream(source, entry.Position, entry.Length)) using (Stream destination = File.Create(Path.Combine(destinationPath, entry.FileName))) { if (archive.IsEncrypted) { using (AesManaged aes = new AesManaged { KeySize = 128, Key = FarcArchive.FarcEncryptionKeyBytes, BlockSize = 128, Mode = CipherMode.ECB, Padding = PaddingMode.Zeros, IV = new byte[16], }) using (CryptoStream cryptoStream = new CryptoStream( entrySource, aes.CreateDecryptor(), CryptoStreamMode.Read)) { if (archive.IsCompressed && entry.Length != entry.CompressedLength) { using (GZipStream gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) { gzipStream.CopyTo(destination); } } else { cryptoStream.CopyTo(destination); } } } else if (archive.IsCompressed && entry.Length != entry.CompressedLength) { using (GZipStream gzipStream = new GZipStream(entrySource, CompressionMode.Decompress)) { gzipStream.CopyTo(destination); } } else { entrySource.CopyTo(destination); } } } } } else if (File.GetAttributes(sourcePath).HasFlag(FileAttributes.Directory)) { FarcArchive archive = new FarcArchive(); archive.Alignment = alignment; archive.IsCompressed = compress; if (destinationPath == null) { destinationPath = sourcePath + ".farc"; } foreach (string fileName in Directory.GetFiles(sourcePath)) { archive.Add(new FarcEntry { FileName = Path.GetFileName(fileName), FilePath = new FileInfo(fileName) }); } archive.Save(destinationPath); } }