/// <summary> /// Open the .far archive which is the given file. /// </summary> /// <param name="path"></param> public FSARPackage(IFile f) { FileName = f.Name; root = new FSARDirectory(null, ROOT_DIR); filestream = f.GetStream(); uint magic = filestream.ReadUInt32BE(); if (magic == 0x46534743) // "FSGC" { throw new NotSupportedException("File is encrypted (FSGC)."); } if (magic != 0x46534152) // "FSAR" { throw new InvalidDataException("File does not have a valid FSAR header."); } filestream.Position = 8; uint file_base = filestream.ReadUInt32BE(); uint num_files = filestream.ReadUInt32BE(); filestream.Position = 0x20; for (int i = 0; i < num_files; i++) { filestream.Position = 0x20 + 0x120 * i; string fpath = filestream.ReadASCIINullTerminated(); filestream.Position = 0x20 + 0x120 * i + 0x100; long size = filestream.ReadInt64BE(); long zsize = filestream.ReadInt64BE(); long offset = filestream.ReadInt64BE(); uint zipped = filestream.ReadUInt32BE(); FSARDirectory dir = makeOrGetDir(fpath); string filename = fpath.Split('\\').Last(); dir.AddFile(new FSARFile(filename, dir, size, zipped != 1, zsize, offset + file_base, filestream)); } }
/// <summary> /// Get the directory at the end of this path, or make it (and all /// intermediate dirs) if it doesn't exist. /// </summary> /// <param name="path"></param> /// <returns></returns> private FSARDirectory makeOrGetDir(string path) { string[] breadcrumbs = path.Split('\\'); IDirectory last = root; IDirectory current; if (breadcrumbs.Length == 1) { return(root); } for (var idx = 0; idx < breadcrumbs.Length - 1; idx++) { if (!last.TryGetDirectory(breadcrumbs[idx], out current)) { current = new FSARDirectory(last, breadcrumbs[idx]); (last as FSARDirectory).AddDir(current as FSARDirectory); } last = current; } return(last as FSARDirectory); }