private bool LoadFile(DuplicatableStream headerStream, DuplicatableStream contentStream) { DuplicatableStream infile = headerStream.Duplicate(); contentFile = contentStream.Duplicate(); infile.Seek(0x00, SeekOrigin.Begin); string magic = infile.ReadAscii(4); if (magic != "FPS4") { Console.WriteLine("Not an FPS4 file!"); return(false); } Endian = Util.Endianness.BigEndian; FileCount = infile.ReadUInt32().FromEndian(Endian); HeaderSize = infile.ReadUInt32().FromEndian(Endian); // if header seems huge then we probably have assumed the wrong endianness if (HeaderSize > 0xFFFF) { Endian = Util.Endianness.LittleEndian; FileCount = FileCount.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian); HeaderSize = HeaderSize.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian); } FirstFileStart = infile.ReadUInt32().FromEndian(Endian); EntrySize = infile.ReadUInt16().FromEndian(Endian); ContentBitmask = new ContentInfo(infile.ReadUInt16().FromEndian(Endian)); Unknown2 = infile.ReadUInt32().FromEndian(Endian); ArchiveNameLocation = infile.ReadUInt32().FromEndian(Endian); infile.Position = ArchiveNameLocation; if (ArchiveNameLocation > 0) { ArchiveName = infile.ReadShiftJisNullterm(); } Alignment = FirstFileStart; Console.WriteLine("Content Bitmask: 0x" + ContentBitmask.Value.ToString("X4")); if (ContentBitmask.HasUnknownDataTypes) { Console.WriteLine("WARNING: Bitmask identifies unknown data types, data interpretation will probably be incorrect."); } Files = new List <FileInfo>((int)FileCount); for (uint i = 0; i < FileCount; ++i) { infile.Position = HeaderSize + (i * EntrySize); Files.Add(new FileInfo(infile, i, ContentBitmask, Endian, Util.GameTextEncoding.ASCII)); } FileLocationMultiplier = CalculateFileLocationMultiplier(); ShouldGuessFilesizeFromNextFile = !ContentBitmask.ContainsFileSizes && !ContentBitmask.ContainsSectorSizes && CalculateIsLinear(); infile.Dispose(); return(true); }
// TODO: Clean up code duplication between Extract(), GetChildByIndex(), GetChildByName(), GetChildNames()! public void Extract(string dirname, bool noMetadataParsing = false, bool printProgressToConsole = false) { System.IO.Directory.CreateDirectory(dirname); for (int i = 0; i < Files.Count - 1; ++i) { FileInfo fi = Files[i]; if (fi.ShouldSkip) { if (printProgressToConsole) { Console.WriteLine("Skipped #" + i.ToString("D4")); } continue; } if (fi.Location == null) { throw new Exception("FPS4 extraction failure: Doesn't contain file start pointers!"); } uint?maybeFilesize = fi.GuessFileSize(ShouldGuessFilesizeFromNextFile ? Files : null); if (maybeFilesize == null) { throw new Exception("FPS4 extraction failure: Doesn't contain filesize information!"); } long fileloc = (long)(fi.Location.Value) * FileLocationMultiplier; uint filesize = maybeFilesize.Value; (string path, string filename) = fi.GuessFilePathName(); if (path != null) { Directory.CreateDirectory(dirname + '/' + path); path = path + '/' + filename; } else { path = filename; } FileStream outfile = new FileStream(Path.Combine(dirname, path), FileMode.Create); if (printProgressToConsole) { Console.WriteLine("Extracting #" + i.ToString("D4") + ": " + path); } contentFile.Seek(fileloc, SeekOrigin.Begin); StreamUtils.CopyStream(contentFile, outfile, (int)filesize); outfile.Close(); } }