예제 #1
0
        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);
        }
예제 #2
0
        // 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();
            }
        }