public FAR3Archive(string Path) { m_ArchivePath = Path; if (isReadingSomething == false) { isReadingSomething = true; try { m_Reader = new BinaryReader(File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read)); } catch (Exception e) { throw new FAR3Exception("Could not open the specified archive - " + Path + "! (FAR3Archive())"); } string Header = Encoding.ASCII.GetString(m_Reader.ReadBytes(8)); uint Version = m_Reader.ReadUInt32(); if ((Header != "FAR!byAZ") || (Version != 3)) { throw new FAR3Exception("Archive wasn't a valid FAR V.3 archive! (FAR3Archive())"); } uint ManifestOffset = m_Reader.ReadUInt32(); m_ManifestOffset = ManifestOffset; m_Reader.BaseStream.Seek(ManifestOffset, SeekOrigin.Begin); uint NumFiles = m_Reader.ReadUInt32(); for (int i = 0; i < NumFiles; i++) { Far3Entry Entry = new Far3Entry(); Entry.DecompressedFileSize = m_Reader.ReadUInt32(); byte[] Dummy = m_Reader.ReadBytes(3); Entry.CompressedFileSize = (uint)((Dummy[0] << 0) | (Dummy[1] << 8) | (Dummy[2]) << 16); Entry.DataType = m_Reader.ReadByte(); Entry.DataOffset = m_Reader.ReadUInt32(); Entry.Compressed = m_Reader.ReadByte(); Entry.AccessNumber = m_Reader.ReadByte(); Entry.FilenameLength = m_Reader.ReadUInt16(); Entry.TypeID = m_Reader.ReadUInt32(); Entry.FileID = m_Reader.ReadUInt32(); Entry.Filename = Encoding.ASCII.GetString(m_Reader.ReadBytes(Entry.FilenameLength)); if (!m_Entries.ContainsKey(Entry.Filename)) m_Entries.Add(Entry.Filename, Entry); m_EntriesList.Add(Entry); m_EntryByID.Add(Entry.FileID, Entry); } //Keep the stream open, it helps peformance. //m_Reader.Close(); isReadingSomething = false; } }
/// <summary> /// Gets an entry's data from a Far3Entry instance. /// </summary> /// <param name="Entry">The Far3Entry instance.</param> /// <returns>The entry's data.</returns> public byte[] GetEntry(Far3Entry Entry) { lock (m_Reader) { m_Reader.BaseStream.Seek((long)Entry.DataOffset, SeekOrigin.Begin); isReadingSomething = true; if (Entry.IsCompressed == 0x01) { m_Reader.ReadBytes(9); uint Filesize = m_Reader.ReadUInt32(); ushort CompressionID = m_Reader.ReadUInt16(); if (CompressionID == 0xFB10) { byte[] Dummy = m_Reader.ReadBytes(3); uint DecompressedSize = (uint)((Dummy[0] << 0x10) | (Dummy[1] << 0x08) | +Dummy[2]); Decompresser Dec = new Decompresser(); Dec.CompressedSize = Filesize; Dec.DecompressedSize = DecompressedSize; byte[] DecompressedData = Dec.Decompress(m_Reader.ReadBytes((int)Filesize)); //m_Reader.Close(); isReadingSomething = false; return(DecompressedData); } else { m_Reader.BaseStream.Seek((m_Reader.BaseStream.Position - 15), SeekOrigin.Begin); byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); //m_Reader.Close(); isReadingSomething = false; return(Data); } } else { byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); //m_Reader.Close(); isReadingSomething = false; return(Data); } } throw new FAR3Exception("FAR3Entry didn't exist in archive - FAR3Archive.GetEntry()"); }
/// <summary> /// Returns a FileID for a rogue file (file that isn't archived). /// </summary> /// <param name="Entry">The entry generated for the file.</param> /// <returns>A FileID (see RogueFileIDs enum in Database.cs)</returns> public static uint GetFileID(Far3Entry Entry) { try { string Filename = Path.GetFileName(Entry.Filename); Filename = Filename.Replace("-", "_"); Filename = Filename.Substring(0, Filename.IndexOf(".")); return (uint)Enum.Parse(typeof(RogueFileIDs), Filename); } catch (ArgumentException) { return (uint)Entry.GetHashCode(); } }
/// <summary> /// Returns a FileID for a rogue file (file that isn't archived). /// </summary> /// <param name="Entry">The entry generated for the file.</param> /// <returns>A FileID (see RogueFileIDs enum in Database.cs)</returns> public static uint GetFileID(Far3Entry Entry) { try { string[] Dirs = Path.GetDirectoryName(Entry.Filename).Split("\\".ToCharArray()); string Filename = Dirs[1] + "_" + Path.GetFileName(Entry.Filename); Filename = Filename.Replace("-", "_"); Filename = Filename.Substring(0, Filename.IndexOf(".")); return (uint)Enum.Parse(typeof(RogueFileIDs), Filename); } catch (ArgumentException) { return (uint)Entry.GetHashCode(); } }
private byte[] GetEntry(Far3Entry Entry) { lock (m_Reader) { //m_Reader = new BinaryReader(File.Open(m_ArchivePath, FileMode.Open, FileAccess.Read)); m_Reader.BaseStream.Seek((long)Entry.DataOffset, SeekOrigin.Begin); isReadingSomething = true; if (Entry.Compressed == 0x01) { m_Reader.ReadBytes(9); uint Filesize = m_Reader.ReadUInt32(); ushort CompressionID = m_Reader.ReadUInt16(); if (CompressionID == 0xFB10) { byte[] Dummy = m_Reader.ReadBytes(3); uint DecompressedSize = (uint)((Dummy[0] << 0x10) | (Dummy[1] << 0x08) | +Dummy[2]); Decompresser Dec = new Decompresser(); Dec.CompressedSize = Filesize; Dec.DecompressedSize = DecompressedSize; byte[] DecompressedData = Dec.Decompress(m_Reader.ReadBytes((int)Filesize)); //m_Reader.Close(); isReadingSomething = false; return DecompressedData; } else { m_Reader.BaseStream.Seek((m_Reader.BaseStream.Position - 15), SeekOrigin.Begin); byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); //m_Reader.Close(); isReadingSomething = false; return Data; } } else { byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); //m_Reader.Close(); isReadingSomething = false; return Data; } } throw new FAR3Exception("FAR3Entry didn't exist in archive - FAR3Archive.GetEntry()"); }
/// <summary> /// Creates a new FAR3Archive instance from a path. /// </summary> /// <param name="Path">The path to the archive.</param> public FAR3Archive(string Path) { m_ArchivePath = Path; if (isReadingSomething == false) { isReadingSomething = true; try { m_Reader = new BinaryReader(File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read)); } catch (Exception) { throw new FAR3Exception("Could not open the specified archive - " + Path + "! (FAR3Archive())"); } string Header = Encoding.ASCII.GetString(m_Reader.ReadBytes(8)); uint Version = m_Reader.ReadUInt32(); if ((Header != "FAR!byAZ") || (Version != 3)) { throw new FAR3Exception("Archive wasn't a valid FAR V.3 archive! (FAR3Archive())"); } uint ManifestOffset = m_Reader.ReadUInt32(); m_ManifestOffset = ManifestOffset; m_Reader.BaseStream.Seek(ManifestOffset, SeekOrigin.Begin); uint NumFiles = m_Reader.ReadUInt32(); for (int i = 0; i < NumFiles; i++) { Far3Entry Entry = new Far3Entry(); Entry.DecompressedFileSize = m_Reader.ReadUInt32(); byte[] Dummy = m_Reader.ReadBytes(3); Entry.CompressedFileSize = (uint)((Dummy[0] << 0) | (Dummy[1] << 8) | (Dummy[2]) << 16); Entry.DataType = m_Reader.ReadByte(); Entry.DataOffset = m_Reader.ReadUInt32(); //Entry.HasFilename = m_Reader.ReadUInt16(); Entry.IsCompressed = m_Reader.ReadByte(); Entry.AccessNumber = m_Reader.ReadByte(); Entry.FilenameLength = m_Reader.ReadUInt16(); Entry.TypeID = m_Reader.ReadUInt32(); Entry.FileID = m_Reader.ReadUInt32(); Entry.Filename = Encoding.ASCII.GetString(m_Reader.ReadBytes(Entry.FilenameLength)); if (!m_Entries.ContainsKey(Entry.Filename)) { m_Entries.Add(Entry.Filename, Entry); } m_EntriesList.Add(Entry); m_EntryByID.Add(Entry.FileID, Entry); //isn't this a bad idea? i have a feeling this is a bad idea... } //Keep the stream open, it helps peformance. //m_Reader.Close(); isReadingSomething = false; } }
/// <summary> /// Adds files from a specified directory to a dictionary of entries. /// </summary> /// <param name="EntryDir">The directory to scan for entries.</param> /// <param name="Filetype">A fully qualified lowercase filetype to scan for (can be empty).</param> /// <param name="Entries">The Dictionary to add entries to.</param> private static void AddFilesFromDir(string EntryDir, string Filetype, ref Dictionary<Far3Entry, string> Entries) { string[] Dirs = Directory.GetDirectories(EntryDir); foreach(string Dir in Dirs) { if (Filetype != "") { if (Dir.Contains(Filetype)) { string[] Files = Directory.GetFiles(Dir); string[] SubDirs = Directory.GetDirectories(Dir); foreach (string Fle in Files) { if (Fle.Contains(".dat")) { FAR3Archive Archive = new FAR3Archive(Fle); foreach (Far3Entry Entry in Archive.GetAllFAR3Entries()) Entries.Add(Entry, Fle.Replace(GlobalSettings.Default.StartupPath, "")); } else { Far3Entry Entry = new Far3Entry(); Entry.Filename = Fle.Replace(GlobalSettings.Default.StartupPath, ""); Entry.FileID = HelperFuncs.GetFileID(Entry); Entry.TypeID = HelperFuncs.GetTypeID(Path.GetExtension(Fle)); HelperFuncs.CheckCollision(Entry.FileID, Entries); //Ignore fonts to minimize the risk of ID collisions. if (!Entry.Filename.Contains(".ttf")) { if (!Entry.Filename.Contains(".ffn")) Entries.Add(Entry, Entry.Filename); } } } foreach (string SubDir in SubDirs) { Files = Directory.GetFiles(SubDir); foreach (string SubFle in Files) { if (SubFle.Contains(".dat")) { FAR3Archive Archive = new FAR3Archive(SubFle); foreach (Far3Entry Entry in Archive.GetAllFAR3Entries()) Entries.Add(Entry, SubFle.Replace(GlobalSettings.Default.StartupPath, "")); } else { Far3Entry Entry = new Far3Entry(); Entry.Filename = SubFle.Replace(GlobalSettings.Default.StartupPath, ""); Entry.FileID = HelperFuncs.GetFileID(Entry); Entry.TypeID = HelperFuncs.GetTypeID(Path.GetExtension(SubFle)); HelperFuncs.CheckCollision(Entry.FileID, Entries); //Ignore fonts to minimize the risk of ID collisions. if (!Entry.Filename.Contains(".ttf")) { if (!Entry.Filename.Contains(".ffn")) Entries.Add(Entry, Entry.Filename); } } } } } } else //Filetype was empty, so just add all filetypes found... { string[] Files = Directory.GetFiles(Dir); string[] SubDirs = Directory.GetDirectories(Dir); foreach (string Fle in Files) { if (Fle.Contains(".dat")) { FAR3Archive Archive = new FAR3Archive(Fle); foreach (Far3Entry Entry in Archive.GetAllFAR3Entries()) Entries.Add(Entry, Fle.Replace(GlobalSettings.Default.StartupPath, "")); } else { Far3Entry Entry = new Far3Entry(); Entry.Filename = Fle.Replace(GlobalSettings.Default.StartupPath, ""); Entry.FileID = HelperFuncs.GetFileID(Entry); Entry.TypeID = HelperFuncs.GetTypeID(Path.GetExtension(Fle)); HelperFuncs.CheckCollision((ulong)(((ulong)Entry.FileID) << 32 | ((ulong)(Entry.TypeID >> 32))), Entries); //Ignore fonts to minimize the risk of ID collisions. if (!Entry.Filename.Contains(".ttf")) { if(!Entry.Filename.Contains(".ffn")) Entries.Add(Entry, Entry.Filename); } } } foreach (string SubDir in SubDirs) { Files = Directory.GetFiles(SubDir); foreach (string SubFle in Files) { if (SubFle.Contains(".dat")) { FAR3Archive Archive = new FAR3Archive(SubFle); foreach (Far3Entry Entry in Archive.GetAllFAR3Entries()) Entries.Add(Entry, SubFle.Replace(GlobalSettings.Default.StartupPath, "")); } else { Far3Entry Entry = new Far3Entry(); Entry.Filename = SubFle.Replace(GlobalSettings.Default.StartupPath, ""); Entry.FileID = HelperFuncs.GetFileID(Entry); Entry.TypeID = HelperFuncs.GetTypeID(Path.GetExtension(SubFle)); HelperFuncs.CheckCollision((ulong)(((ulong)Entry.FileID) << 32 | ((ulong)(Entry.TypeID >> 32))), Entries); //Ignore fonts to minimize the risk of ID collisions. if (!Entry.Filename.Contains(".ttf")) { if (!Entry.Filename.Contains(".ffn")) Entries.Add(Entry, Entry.Filename); } } } } } } }
private byte[] GetEntry(Far3Entry Entry) { m_Reader = new BinaryReader(File.Open(m_ArchivePath, FileMode.Open)); m_Reader.BaseStream.Seek((long)Entry.DataOffset, SeekOrigin.Begin); if (Entry.Compressed == 0x01) { m_Reader.ReadBytes(9); uint Filesize = m_Reader.ReadUInt32(); ushort CompressionID = m_Reader.ReadUInt16(); if (CompressionID == 0xFB10) { byte[] Dummy = m_Reader.ReadBytes(3); uint DecompressedSize = (uint)((Dummy[0] << 0x10) | (Dummy[1] << 0x08) | +Dummy[2]); Decompresser Dec = new Decompresser(); Dec.CompressedSize = Filesize; Dec.DecompressedSize = DecompressedSize; byte[] DecompressedData = Dec.Decompress(m_Reader.ReadBytes((int)Filesize)); m_Reader.Close(); return DecompressedData; } else { m_Reader.BaseStream.Seek((m_Reader.BaseStream.Position - 15), SeekOrigin.Begin); byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); m_Reader.Close(); return Data; } } else { byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize); m_Reader.Close(); return Data; } throw new FAR3Exception("FileID didn't match any in the archive! (FAR3Archive.GetItemByID())"); }
public byte[] GetItemByID(uint FileID) { Far3Entry[] entries = new Far3Entry[m_Entries.Count]; m_Entries.Values.CopyTo(entries, 0); Far3Entry Entry = Array.Find(entries, delegate(Far3Entry entry) { return entry.FileID == FileID; }); return GetEntry(Entry); }