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; }
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>(); }
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++; } } } }