예제 #1
0
 internal STFSFile(string name, uint size, int startBlock, int numBlocks, STFSDirectory parent, STFSPackage container)
 {
     Name            = name;
     Parent          = parent;
     Size            = size;
     this.dataBlocks = null;
     this.startBlock = startBlock;
     this.numBlocks  = numBlocks;
     this.container  = container;
 }
예제 #2
0
 internal STFSFile(string name, uint size, int[] dataBlocks, STFSDirectory parent, STFSPackage container)
 {
     Name            = name;
     Parent          = parent;
     Size            = size;
     this.dataBlocks = dataBlocks;
     numBlocks       = dataBlocks.Length;
     if (numBlocks > 0)
     {
         startBlock = dataBlocks[0];
     }
     this.container = container;
     ExtendedInfo   = new Dictionary <string, object>();
 }
예제 #3
0
        private STFSPackage(IFile f)
        {
            Stream input = f.GetStream();

            FileName = f.Name;
            disposed = false;

            stream = input;

            // Set the type of STFS file.
            string magic = stream.ReadASCIINullTerminated(4);

            switch (magic)
            {
            case "CON ":
                Type = STFSType.CON;
                break;

            case "LIVE":
                Type = STFSType.LIVE;
                break;

            case "PIRS":
                Type = STFSType.PIRS;
                break;

            default:
                throw new InvalidDataException("STFS is not CON, LIVE, or PIRS");
            }

            BlockCache = new byte[0x1000];

            // Set up STFS info.
            stream.Position = 0x340;
            headerSize      = stream.ReadInt32BE();

            if ((((headerSize + 0xFFF) & 0xF000) >> 0xC) == 0xB)
            {
                tableSizeShift = 0;
            }
            else
            {
                tableSizeShift = 1;
            }

            // Volume Descriptor begins at 0x379
            stream.Position      = 0x37C;
            fileTableBlockCount  = stream.ReadInt16LE();
            fileTableBlockNumber = stream.ReadInt24LE();

            stream.Position = 0x39D;
            fileCount       = stream.ReadInt32LE();

#if !MINIMAL
            // Read both package thumbnails into Image instances
            stream.Position = 0x1712;
            int thumbnailImgSize      = stream.ReadInt32BE();
            int titleThumbnailImgSize = stream.ReadInt32BE();
            stream.Position = 0x171A;
            if (thumbnailImgSize > 0)
            {
                Thumbnail = System.Drawing.Image.FromStream(new System.IO.MemoryStream(stream.ReadBytes(thumbnailImgSize)));
            }
            stream.Position = 0x571A;
            if (titleThumbnailImgSize > 0)
            {
                TitleThumbnail = System.Drawing.Image.FromStream(new System.IO.MemoryStream(stream.ReadBytes(titleThumbnailImgSize)));
            }
#endif

            root = new STFSDirectory(null, ROOT_DIR);
            var dirsOrdinal = new Dictionary <int, STFSDirectory>();
            dirsOrdinal.Add(-1, root);
            int   items           = 0;
            int[] fileTableBlocks = GetFileBlocks(fileTableBlockNumber, fileTableBlockCount, false);
            for (var x = 0; x < fileTableBlocks.Length; x++)
            {
                var  curBlock = fileTableBlocks[x];
                long basePosition;
                CacheBlockAt(BlockToOffset(curBlock));
                using (var curBlockStream = new System.IO.MemoryStream(BlockCache))
                {
                    for (var i = 0; i < 0x40; i++)
                    {
                        basePosition            = 0x40 * i;
                        curBlockStream.Position = basePosition;
                        if (curBlockStream.ReadByte() == 0)
                        {
                            break;
                        }
                        curBlockStream.Position = basePosition + 0x28;
                        byte flags = (byte)curBlockStream.ReadByte();
                        curBlockStream.Position = basePosition;
                        String name;
                        using (var sr = new System.IO.StreamReader(
                                   new System.IO.MemoryStream(curBlockStream.ReadBytes(flags & 0x3f)), Encoding.GetEncoding(1252)))
                        {
                            name = sr.ReadToEnd();
                        }
                        curBlockStream.Position = basePosition + 0x29;
                        int numBlocks = curBlockStream.ReadInt24LE();
                        curBlockStream.ReadInt24LE();
                        int           startBlock = curBlockStream.ReadInt24LE();
                        int           parentDir  = curBlockStream.ReadInt16BE();
                        uint          size       = curBlockStream.ReadUInt32BE();
                        int           update     = curBlockStream.ReadInt32BE();
                        int           access     = curBlockStream.ReadInt32BE();
                        STFSDirectory parent;
                        if (!dirsOrdinal.TryGetValue(parentDir, out parent)) // get the parent if it exists
                        {
                            throw new InvalidDataException("File references non-existent directory.");
                        }

                        if ((flags & 0x80) == 0x80)
                        {
                            // item is a directory
                            var tmp = new STFSDirectory(parent, name);
                            dirsOrdinal.Add(items, tmp);
                            parent.AddDir(tmp);
                        }
                        else
                        {
                            // item is a file
                            STFSFile tmp;
                            if ((flags & 0x40) == 0x40) // blocks are sequential
                            {
                                var dataBlocks = GetFileBlocks(startBlock, numBlocks, (flags & 0x40) == 0x40);
                                tmp = new STFSFile(name, size, dataBlocks, parent, this);
                            }
                            else // offload block calculation until we need it
                            {
                                tmp = new STFSFile(name, size, startBlock, numBlocks, parent, this);
                            }
                            parent.AddFile(tmp);
                        }
                        items++;
                    }
                }
            }
        }