/// <summary> /// Parse a directory for its contents. /// </summary> /// <param name="name">The name of this directory.</param> /// <param name="base_offset">Location of its filename infos.</param> /// <param name="nodes">File descriptor dictionary</param> /// <returns></returns> private FSGIMGDirectory RecursivelyGetFiles(FSGIMGDirectory parent, string name, long base_offset, string path_acc, Dictionary <uint, file_descriptor> nodes) { filestream.Position = base_offset; string filename; FSGIMGDirectory ret = new FSGIMGDirectory(parent, name, base_offset); while ((filename = filestream.ReadASCIINullTerminated()) != "") { long pos = filestream.Position; string real_name = filename.Substring(1); file_descriptor desc; string nextPath = path_acc == "" ? real_name : $"{path_acc}/{real_name}"; nodes.TryGetValue(Hash(nextPath), out desc); if (filename[0] == 'D') { ret.AddDir(RecursivelyGetFiles(ret, real_name, desc.data_offset, nextPath, nodes)); filestream.Position = pos; } else if (filename[0] == 'F') { ret.AddFile(new OffsetFile(real_name, ret, filestream, desc.data_offset, desc.size)); } else { throw new InvalidDataException($"Got invalid filename prefix: {filename[0]}."); } } return(ret); }
public FSGIMGPackage(IFile f) { FileName = f.Name; var parts = new List <Stream>(1); parts.Add(f.GetStream()); if (f.Name.Split('.').Length > 2) // this is a .part* file { int partNum = 1; IFile tmp; while (f.Parent.TryGetFile(f.Name.Substring(0, f.Name.Length - 1) + partNum, out tmp)) { var fs = tmp.GetStream(); parts.Add(fs); partNum++; } } filestream = new MultiStream(parts); if (filestream.ReadASCIINullTerminated(16) != "FSG-FILE-SYSTEM") { throw new InvalidDataException("FSG-FILE-SYSTEM header not found."); } filestream.ReadUInt32BE(); // unknown, == 2 uint header_length = filestream.ReadUInt32BE(); uint num_sectors = filestream.ReadUInt32BE(); //points to a list of all (used) sectors? //starting at 0x180 and increasing by 0x80 up to (num_sectors + 3) << 17 uint sectormap_offset = filestream.ReadUInt32BE(); uint base_offset = filestream.ReadUInt32BE(); filestream.ReadUInt32BE(); // unknown, read buffer size? filestream.ReadUInt32BE(); // unknown, == 8 uint num_files = filestream.ReadUInt32BE(); uint zero = filestream.ReadUInt32BE(); uint checksum = filestream.ReadUInt32BE(); var nodes = new Dictionary <uint, file_descriptor>((int)num_files); byte[] sector_types = new byte[num_sectors + (base_offset >> 17)]; for (var i = 0; i < num_files; i++) { var node = new file_descriptor(); node.filename_hash = filestream.ReadUInt32BE(); node.type = (byte)filestream.ReadByte(); node.offset = filestream.ReadUInt24BE(); nodes.Add(node.filename_hash, node); } foreach (file_descriptor node in nodes.Values) { filestream.Position = node.offset; long offset = filestream.ReadUInt32BE(); node.data_offset = (offset << 10) + base_offset; node.size = filestream.ReadUInt32BE(); } root = RecursivelyGetFiles(null, ROOT_DIR, base_offset, "", nodes); }