예제 #1
0
        public OneStorybookArchiveReader(Stream source) : base(source)
        {
            _prsCompression = new PrsCompression();

            // Get the number of entries in the archive
            int numEntries = PTStream.ReadInt32BE(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                string entryFilename = PTStream.ReadCStringAt(source, 0x10 + (i * 0x30), 0x20);

                source.Position = 0x34 + (i * 0x30);
                int entryOffset = PTStream.ReadInt32BE(source);
                int entryLength = PTStream.ReadInt32BE(source);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #2
0
        public TexArchiveReader(Stream source) : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            source.Position += 8;

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry filename extension, offset, length, and filename without the extension
                string entryFileExtension = PTStream.ReadCString(source, 4, Encoding.GetEncoding("Shift_JIS"));
                int    entryOffset        = PTStream.ReadInt32(source);
                int    entryLength        = PTStream.ReadInt32(source);
                string entryFilename      = PTStream.ReadCString(source, 20, Encoding.GetEncoding("Shift_JIS"));

                if (entryFileExtension != String.Empty)
                {
                    entryFileExtension = "." + entryFileExtension;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename + entryFileExtension);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #3
0
        public TexArchiveReader(Stream source)
            : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            source.Position += 8;

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry filename extension, offset, length, and filename without the extension
                string entryFileExtension = PTStream.ReadCString(source, 4, Encoding.GetEncoding("Shift_JIS"));
                int entryOffset = PTStream.ReadInt32(source);
                int entryLength = PTStream.ReadInt32(source);
                string entryFilename = PTStream.ReadCString(source, 20, Encoding.GetEncoding("Shift_JIS"));

                if (entryFileExtension != String.Empty)
                    entryFileExtension = "." + entryFileExtension;

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename + entryFileExtension);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #4
0
        public SntArchiveReader(Stream source)
            : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 48;
            int numEntries = PTStream.ReadInt32(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            source.Position += 8 + (numEntries * 20);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Readin the entry offset and length
                int entryLength = PTStream.ReadInt32(source);
                int entryOffset = PTStream.ReadInt32(source) + 32;

                // If this archive contains GIM textures, then it's possible that they may contain filenames.
                // Let's check and see
                string entryFname = String.Empty;
                if (entryLength > 40)
                {
                    long oldPosition = source.Position;
                    source.Position = startOffset + entryOffset;

                    if ((new GimTexture()).Is(source, entryLength, String.Empty))
                    {
                        // It's a GIM texture. Let's try to find a filename
                        source.Position += 36;
                        long fnameOffset = PTStream.ReadInt32(source) + 48;

                        if (fnameOffset < source.Length)
                        {
                            source.Position = startOffset + entryOffset + fnameOffset;
                            entryFname = Path.GetFileNameWithoutExtension(PTStream.ReadCString(source, (int)(source.Length - fnameOffset)));

                            if (entryFname != String.Empty)
                            {
                                entryFname += ".gim";
                            }
                        }
                    }

                    source.Position = oldPosition;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #5
0
        public SntArchiveReader(Stream source) : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 48;
            int numEntries = PTStream.ReadInt32(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            source.Position += 8 + (numEntries * 20);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Readin the entry offset and length
                int entryLength = PTStream.ReadInt32(source);
                int entryOffset = PTStream.ReadInt32(source) + 32;

                // If this archive contains GIM textures, then it's possible that they may contain filenames.
                // Let's check and see
                string entryFname = String.Empty;
                if (entryLength > 40)
                {
                    long oldPosition = source.Position;
                    source.Position = startOffset + entryOffset;

                    if ((new GimTexture()).Is(source, entryLength, String.Empty))
                    {
                        // It's a GIM texture. Let's try to find a filename
                        source.Position += 36;
                        long fnameOffset = PTStream.ReadInt32(source) + 48;

                        if (fnameOffset < source.Length)
                        {
                            source.Position = startOffset + entryOffset + fnameOffset;
                            entryFname      = Path.GetFileNameWithoutExtension(PTStream.ReadCString(source, (int)(source.Length - fnameOffset)));

                            if (entryFname != String.Empty)
                            {
                                entryFname += ".gim";
                            }
                        }
                    }

                    source.Position = oldPosition;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #6
0
        public TxdStorybookArchiveReader(Stream source) : base(source)
        {
            var fileCount = PTStream.ReadInt32BEAt(source, 0x4);

            entries = new ArchiveEntryCollection(this, fileCount);

            for (int i = 0; i < fileCount; i++)
            {
                var fileName = PTStream.ReadCStringAt(source, 0x10 + (i * 0x28), 32);
                var offset   = PTStream.ReadUInt32BEAt(source, 0x08 + (i * 0x28));
                var length   = PTStream.ReadInt32BEAt(source, 0x0C + (i * 0x28));

                fileName = string.IsNullOrWhiteSpace(fileName) ? fileName : Path.ChangeExtension(fileName, "GVR");

                entries.Add(startOffset + offset, length, fileName);
            }
        }
예제 #7
0
        public AcxArchiveReader(Stream source)
            : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32BE(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry offset and length
                int entryOffset = PTStream.ReadInt32BE(source);
                int entryLength = PTStream.ReadInt32BE(source);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, String.Empty);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #8
0
        public AcxArchiveReader(Stream source) : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32BE(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry offset and length
                int entryOffset = PTStream.ReadInt32BE(source);
                int entryLength = PTStream.ReadInt32BE(source);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, String.Empty);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #9
0
        public AfsArchiveReader(Stream source) : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Get the offset of the metadata
            source.Position += (numEntries * 8);
            int metadataOffset = PTStream.ReadInt32(source);

            // If the offset isn't stored there, then it is stored right before the offset of the first entry
            if (metadataOffset == 0)
            {
                source.Position = startOffset + 8;
                source.Position = PTStream.ReadInt32(source) - 8;
                metadataOffset  = PTStream.ReadInt32(source);
            }

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry offset and length
                source.Position = startOffset + 8 + (i * 8);
                int entryOffset = PTStream.ReadInt32(source);
                int entryLength = PTStream.ReadInt32(source);

                // Read in the entry file name
                source.Position = metadataOffset + (i * 48);
                string entryFname = PTStream.ReadCString(source, 32);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #10
0
        public AfsArchiveReader(Stream source)
            : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            // Get the offset of the metadata
            source.Position += (numEntries * 8);
            int metadataOffset = PTStream.ReadInt32(source);

            // If the offset isn't stored there, then it is stored right before the offset of the first entry
            if (metadataOffset == 0)
            {
                source.Position = startOffset + 8;
                source.Position = PTStream.ReadInt32(source) - 8;
                metadataOffset = PTStream.ReadInt32(source);
            }

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry offset and length
                source.Position = startOffset + 8 + (i * 8);
                int entryOffset = PTStream.ReadInt32(source);
                int entryLength = PTStream.ReadInt32(source);

                // Read in the entry file name
                source.Position = metadataOffset + (i * 48);
                string entryFname = PTStream.ReadCString(source, 32);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #11
0
        public OneUnleashedArchiveReader(Stream source) : base(source)
        {
            // Get the number of entries in the archive
            source.Position += 4;
            int numEntries = PTStream.ReadInt32(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // Read in the entry filename, offset, and length
                string entryFilename = PTStream.ReadCString(source, 56);
                int    entryOffset   = PTStream.ReadInt32(source);
                int    entryLength   = PTStream.ReadInt32(source);

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #12
0
        public ArchiveWriter(Stream destination)
        {
            this.destination = destination;

            entries = new ArchiveEntryCollection(this);
        }
예제 #13
0
        public PvmArchiveReader(Stream source) : base(source)
        {
            // The offset of the first entry
            source.Position += 4;
            int entryOffset  = PTStream.ReadInt32(source) + 8;
            int headerOffset = 0xC;

            // Read what properties this archive stores for each texture
            byte properties = PTStream.ReadByte(source);

            hasFilenames     = (properties & (1 << 3)) > 0;
            hasFormats       = (properties & (1 << 2)) > 0;
            hasDimensions    = (properties & (1 << 1)) > 0;
            hasGlobalIndexes = (properties & (1 << 0)) > 0;
            source.Position++;

            // Determine the size of each entry in the entry table
            tableEntryLength = 2;
            if (hasFilenames)
            {
                tableEntryLength += 28;
            }
            if (hasFormats)
            {
                tableEntryLength += 2;
            }
            if (hasDimensions)
            {
                tableEntryLength += 2;
            }

            if (hasGlobalIndexes)
            {
                globalIndexOffset = tableEntryLength;
                tableEntryLength += 4;
            }

            // Get the number of entries in the archive
            ushort numEntries = PTStream.ReadUInt16(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // We need to need to determine the offset based on the length,
                // which is stored in the texture data.
                // We already have the entry offset
                source.Position = startOffset + entryOffset + 4;
                int entryLength = PTStream.ReadInt32(source) + 8;

                string entryFname = String.Empty;
                if (hasFilenames)
                {
                    source.Position = startOffset + headerOffset + 2;
                    entryFname      = PTStream.ReadCString(source, 28) + ".pvr";
                    headerOffset   += tableEntryLength;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);

                entryOffset += entryLength;
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #14
0
        public PvmArchiveReader(Stream source)
            : base(source)
        {
            // The offset of the first entry
            source.Position += 4;
            int entryOffset = PTStream.ReadInt32(source) + 8;
            int headerOffset = 0xC;

            // Read what properties this archive stores for each texture
            byte properties  = PTStream.ReadByte(source);
            hasFilenames     = (properties & (1 << 3)) > 0;
            hasFormats       = (properties & (1 << 2)) > 0;
            hasDimensions    = (properties & (1 << 1)) > 0;
            hasGlobalIndexes = (properties & (1 << 0)) > 0;
            source.Position++;

            // Determine the size of each entry in the entry table
            tableEntryLength = 2;
            if (hasFilenames)  tableEntryLength += 28;
            if (hasFormats)    tableEntryLength += 2;
            if (hasDimensions) tableEntryLength += 2;

            if (hasGlobalIndexes)
            {
                globalIndexOffset = tableEntryLength;
                tableEntryLength += 4;
            }

            // Get the number of entries in the archive
            ushort numEntries = PTStream.ReadUInt16(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // We need to need to determine the offset based on the length,
                // which is stored in the texture data.
                // We already have the entry offset
                source.Position = startOffset + entryOffset + 4;
                int entryLength = PTStream.ReadInt32(source) + 8;

                string entryFname = String.Empty;
                if (hasFilenames)
                {
                    source.Position = startOffset + headerOffset + 2;
                    entryFname = PTStream.ReadCString(source, 28) + ".pvr";
                    headerOffset += tableEntryLength;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);

                entryOffset += entryLength;
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #15
0
        public ArchiveWriter(Stream destination)
        {
            this.destination = destination;

            entries = new ArchiveEntryCollection(this);
        }
예제 #16
0
        public NarcArchiveReader(Stream source)
            : base(source)
        {
            // Read the archive header
            source.Position += 12;
            ushort fatbOffset = PTStream.ReadUInt16(source); // Should always be 0x10

            // Read the FATB chunk
            source.Position = startOffset + fatbOffset + 4;
            uint fntbOffset = fatbOffset + PTStream.ReadUInt32(source);

            // Get the number of entries in the archive
            int numEntries = PTStream.ReadInt32(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            // Let's check to see if this is a Puyo Tetris PS3 NARC by checking the offset of the first file.
            // It seems that offsets are stored differently than a normal NARC.
            bool isPs3Narc = (PTStream.ReadUInt32(source) == 0);

            // This is a Puyo Tetris PS3 NARC.
            if (isPs3Narc)
            {
                // Read the FNTB chunk
                source.Position = startOffset + fntbOffset + 4;
                uint fimgOffset = fntbOffset + PTStream.ReadUInt32(source);
                bool hasFilenames = (fimgOffset - fntbOffset != 16);
                uint filenameOffset = fntbOffset + 8 + PTStream.ReadUInt32(source);

                // Read in all the entries
                source.Position = startOffset + fatbOffset + 12;
                for (int i = 0; i < numEntries; i++)
                {
                    // Read the entry offset and length
                    int entryOffset = PTStream.ReadInt32(source);
                    int entryLength = PTStream.ReadInt32(source) - entryOffset;

                    // Read the filename (if it has one)
                    string entryFname = String.Empty;
                    if (hasFilenames)
                    {
                        long oldPosition = source.Position;
                        source.Position = startOffset + filenameOffset;

                        byte fnameLength = PTStream.ReadByte(source);

                        // Puyo Tools can't handle directory names. Just skip over them for now.
                        if ((fnameLength & 0x80) != 0)
                        {
                            // Go only up to fimgOffset to prevent an infinite loop
                            // (though that should never happen for a properly formatted NARC).
                            while ((fnameLength & 0x80) != 0 && filenameOffset < fimgOffset)
                            {
                                fnameLength &= 0x7F;
                                filenameOffset += (uint)(fnameLength + 4);
                                source.Position += fnameLength + 3;
                                fnameLength = PTStream.ReadByte(source);
                            }
                        }

                        entryFname = PTStream.ReadCString(source, fnameLength);
                        filenameOffset += (uint)(fnameLength + 1);

                        source.Position = oldPosition;
                    }

                    // Add this entry to the collection
                    entries.Add(startOffset + fimgOffset + 8 + entryOffset, entryLength, entryFname);
                }
            }

            // This is a NDS NARC.
            else
            {
                // Read the FNTB chunk
                source.Position = startOffset + fntbOffset + 4;
                bool hasFilenames = (PTStream.ReadUInt32(source) == 8);
                uint filenameOffset = fntbOffset + 8 + PTStream.ReadUInt32(source);

                // Read in all the entries
                source.Position = startOffset + fatbOffset + 12;
                for (int i = 0; i < numEntries; i++)
                {
                    // Read the entry offset and length
                    int entryOffset = PTStream.ReadInt32(source);
                    int entryLength = PTStream.ReadInt32(source) - entryOffset;

                    // Read the filename (if it has one)
                    string entryFname = String.Empty;
                    if (hasFilenames)
                    {
                        long oldPosition = source.Position;
                        source.Position = startOffset + filenameOffset;

                        byte fnameLength = PTStream.ReadByte(source);
                        entryFname = PTStream.ReadCString(source, fnameLength);
                        filenameOffset += (uint)(fnameLength + 1);

                        source.Position = oldPosition;
                    }

                    // Add this entry to the collection
                    entries.Add(startOffset + entryOffset, entryLength, entryFname);
                }
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #17
0
        public U8ArchiveReader(Stream source) : base(source)
        {
            // Read the archive header
            source.Position += 4;
            uint rootNodeOffset = PTStream.ReadUInt32BE(source);
            uint nodesLength    = PTStream.ReadUInt32BE(source);
            uint dataOffset     = PTStream.ReadUInt32BE(source);

            // Go the root node
            source.Position = startOffset + rootNodeOffset;
            Node rootNode = new Node();

            rootNode.Type       = PTStream.ReadByte(source);
            rootNode.NameOffset = (uint)(PTStream.ReadByte(source) << 24 | PTStream.ReadUInt16BE(source));
            rootNode.DataOffset = PTStream.ReadUInt32BE(source);
            rootNode.Length     = PTStream.ReadUInt32BE(source);

            entries = new ArchiveEntryCollection(this, (int)rootNode.Length - 1);
            uint stringTableOffset = rootNodeOffset + (rootNode.Length * 12);

            // rootNode.Length is essentially how many files are contained in the archive, so we'll do just that
            for (int i = 0; i < rootNode.Length - 1; i++)
            {
                // Read in this node
                Node node = new Node();
                node.Type       = PTStream.ReadByte(source);
                node.NameOffset = (uint)(PTStream.ReadByte(source) << 24 | PTStream.ReadUInt16BE(source));
                node.DataOffset = PTStream.ReadUInt32BE(source);
                node.Length     = PTStream.ReadUInt32BE(source);

                // Create the archive entry, then check what type of node it is
                long   entryOffset = 0;
                int    entryLength = 0;
                string entryFilename;

                // A file node
                if (node.Type == 0)
                {
                    entryOffset = startOffset + node.DataOffset;
                    entryLength = (int)node.Length;
                }

                // A directory node
                // In its present state, Puyo Tools can't handle directories in archives.
                // In the meantime, we'll just skip it
                else if (node.Type == 1)
                {
                    continue;
                }

                // Get the filename for the entry
                long oldPosition = source.Position;
                source.Position = startOffset + stringTableOffset + node.NameOffset;
                entryFilename   = PTStream.ReadCString(source);
                source.Position = oldPosition;

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #18
0
        public GvmArchiveReader(Stream source)
            : base(source)
        {
            // The offset of the first entry
            source.Position += 4;
            int entryOffset = PTStream.ReadInt32(source) + 8;
            int headerOffset = 0xC;

            // Read what properties this archive stores for each texture
            source.Position++;
            byte properties  = PTStream.ReadByte(source);
            hasFilenames     = (properties & (1 << 3)) > 0;
            hasFormats       = (properties & (1 << 2)) > 0;
            hasDimensions    = (properties & (1 << 1)) > 0;
            hasGlobalIndexes = (properties & (1 << 0)) > 0;

            // Determine the size of each entry in the file table
            tableEntryLength = 2;
            if (hasFilenames)  tableEntryLength += 28;
            if (hasFormats)    tableEntryLength += 2;
            if (hasDimensions) tableEntryLength += 2;

            if (hasGlobalIndexes)
            {
                globalIndexOffset = tableEntryLength;
                tableEntryLength += 4;
            }

            // Get the number of entries in the archive
            ushort numEntries = PTStream.ReadUInt16BE(source);
            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // We need to need to determine the offset based on the length, which is stored in the texture data.
                // We already have the entry offset.
                source.Position = startOffset + entryOffset + 4;
                int entryLength = PTStream.ReadInt32(source) + 8;

                string entryFname = String.Empty;
                if (hasFilenames)
                {
                    source.Position = startOffset + headerOffset + 2;
                    entryFname = PTStream.ReadCString(source, 28) + ".gvr";
                    headerOffset += tableEntryLength;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);

                entryOffset += entryLength;
            }

            // Some Billy Hatcher textures have an oddity where the texture length is 16 more than what it
            // actually should be. This seems to only effect the last texture of a GVM, and only some of them
            // are affected. In that case, we will "fix" the GVRs in question.
            needToFix = (entryOffset > source.Length);

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #19
0
        public U8ArchiveReader(Stream source)
            : base(source)
        {
            // Read the archive header
            source.Position += 4;
            uint rootNodeOffset = PTStream.ReadUInt32BE(source);
            uint nodesLength = PTStream.ReadUInt32BE(source);
            uint dataOffset = PTStream.ReadUInt32BE(source);

            // Go the root node
            source.Position = startOffset + rootNodeOffset;
            Node rootNode = new Node();
            rootNode.Type = PTStream.ReadByte(source);
            rootNode.NameOffset = (uint)(PTStream.ReadByte(source) << 24 | PTStream.ReadUInt16BE(source));
            rootNode.DataOffset = PTStream.ReadUInt32BE(source);
            rootNode.Length = PTStream.ReadUInt32BE(source);

            entries = new ArchiveEntryCollection(this, (int)rootNode.Length - 1);
            uint stringTableOffset = rootNodeOffset + (rootNode.Length * 12);

            // rootNode.Length is essentially how many files are contained in the archive, so we'll do just that
            for (int i = 0; i < rootNode.Length - 1; i++)
            {
                // Read in this node
                Node node = new Node();
                node.Type = PTStream.ReadByte(source);
                node.NameOffset = (uint)(PTStream.ReadByte(source) << 24 | PTStream.ReadUInt16BE(source));
                node.DataOffset = PTStream.ReadUInt32BE(source);
                node.Length = PTStream.ReadUInt32BE(source);

                // Create the archive entry, then check what type of node it is
                long entryOffset = 0;
                int entryLength = 0;
                string entryFilename;

                // A file node
                if (node.Type == 0)
                {
                    entryOffset = startOffset + node.DataOffset;
                    entryLength = (int)node.Length;
                }

                // A directory node
                // In its present state, Puyo Tools can't handle directories in archives.
                // In the meantime, we'll just skip it
                else if (node.Type == 1)
                {
                    continue;
                }

                // Get the filename for the entry
                long oldPosition = source.Position;
                source.Position = startOffset + stringTableOffset + node.NameOffset;
                entryFilename = PTStream.ReadCString(source);
                source.Position = oldPosition;

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFilename);
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #20
0
        public NarcArchiveReader(Stream source) : base(source)
        {
            // Read the archive header
            source.Position += 12;
            ushort fatbOffset = PTStream.ReadUInt16(source); // Should always be 0x10

            // Read the FATB chunk
            source.Position = startOffset + fatbOffset + 4;
            uint fntbOffset = fatbOffset + PTStream.ReadUInt32(source);


            // Get the number of entries in the archive
            int numEntries = PTStream.ReadInt32(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Let's check to see if this is a Puyo Tetris PS3 NARC by checking the offset of the first file.
            // It seems that offsets are stored differently than a normal NARC.
            bool isPs3Narc = (PTStream.ReadUInt32(source) == 0);

            // This is a Puyo Tetris PS3 NARC.
            if (isPs3Narc)
            {
                // Read the FNTB chunk
                source.Position = startOffset + fntbOffset + 4;
                uint fimgOffset     = fntbOffset + PTStream.ReadUInt32(source);
                bool hasFilenames   = (fimgOffset - fntbOffset != 16);
                uint filenameOffset = fntbOffset + 8 + PTStream.ReadUInt32(source);

                // Read in all the entries
                source.Position = startOffset + fatbOffset + 12;
                for (int i = 0; i < numEntries; i++)
                {
                    // Read the entry offset and length
                    int entryOffset = PTStream.ReadInt32(source);
                    int entryLength = PTStream.ReadInt32(source) - entryOffset;

                    // Read the filename (if it has one)
                    string entryFname = String.Empty;
                    if (hasFilenames)
                    {
                        long oldPosition = source.Position;
                        source.Position = startOffset + filenameOffset;

                        byte fnameLength = PTStream.ReadByte(source);

                        // Puyo Tools can't handle directory names. Just skip over them for now.
                        if ((fnameLength & 0x80) != 0)
                        {
                            // Go only up to fimgOffset to prevent an infinite loop
                            // (though that should never happen for a properly formatted NARC).
                            while ((fnameLength & 0x80) != 0 && filenameOffset < fimgOffset)
                            {
                                fnameLength     &= 0x7F;
                                filenameOffset  += (uint)(fnameLength + 4);
                                source.Position += fnameLength + 3;
                                fnameLength      = PTStream.ReadByte(source);
                            }
                        }

                        entryFname      = PTStream.ReadCString(source, fnameLength);
                        filenameOffset += (uint)(fnameLength + 1);

                        source.Position = oldPosition;
                    }

                    // Add this entry to the collection
                    entries.Add(startOffset + fimgOffset + 8 + entryOffset, entryLength, entryFname);
                }
            }

            // This is a NDS NARC.
            else
            {
                // Read the FNTB chunk
                source.Position = startOffset + fntbOffset + 4;
                bool hasFilenames   = (PTStream.ReadUInt32(source) == 8);
                uint filenameOffset = fntbOffset + 8 + PTStream.ReadUInt32(source);

                // Read in all the entries
                source.Position = startOffset + fatbOffset + 12;
                for (int i = 0; i < numEntries; i++)
                {
                    // Read the entry offset and length
                    int entryOffset = PTStream.ReadInt32(source);
                    int entryLength = PTStream.ReadInt32(source) - entryOffset;

                    // Read the filename (if it has one)
                    string entryFname = String.Empty;
                    if (hasFilenames)
                    {
                        long oldPosition = source.Position;
                        source.Position = startOffset + filenameOffset;

                        byte fnameLength = PTStream.ReadByte(source);
                        entryFname      = PTStream.ReadCString(source, fnameLength);
                        filenameOffset += (uint)(fnameLength + 1);

                        source.Position = oldPosition;
                    }

                    // Add this entry to the collection
                    entries.Add(startOffset + entryOffset, entryLength, entryFname);
                }
            }

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }
예제 #21
0
        public GvmArchiveReader(Stream source) : base(source)
        {
            // The offset of the first entry
            source.Position += 4;
            int entryOffset  = PTStream.ReadInt32(source) + 8;
            int headerOffset = 0xC;

            // Read what properties this archive stores for each texture
            source.Position++;
            byte properties = PTStream.ReadByte(source);

            hasFilenames     = (properties & (1 << 3)) > 0;
            hasFormats       = (properties & (1 << 2)) > 0;
            hasDimensions    = (properties & (1 << 1)) > 0;
            hasGlobalIndexes = (properties & (1 << 0)) > 0;

            // Determine the size of each entry in the file table
            tableEntryLength = 2;
            if (hasFilenames)
            {
                tableEntryLength += 28;
            }
            if (hasFormats)
            {
                tableEntryLength += 2;
            }
            if (hasDimensions)
            {
                tableEntryLength += 2;
            }

            if (hasGlobalIndexes)
            {
                globalIndexOffset = tableEntryLength;
                tableEntryLength += 4;
            }

            // Get the number of entries in the archive
            ushort numEntries = PTStream.ReadUInt16BE(source);

            entries = new ArchiveEntryCollection(this, numEntries);

            // Read in all the entries
            for (int i = 0; i < numEntries; i++)
            {
                // We need to need to determine the offset based on the length, which is stored in the texture data.
                // We already have the entry offset.
                source.Position = startOffset + entryOffset + 4;
                int entryLength = PTStream.ReadInt32(source) + 8;

                string entryFname = String.Empty;
                if (hasFilenames)
                {
                    source.Position = startOffset + headerOffset + 2;
                    entryFname      = PTStream.ReadCString(source, 28) + ".gvr";
                    headerOffset   += tableEntryLength;
                }

                // Add this entry to the collection
                entries.Add(startOffset + entryOffset, entryLength, entryFname);

                entryOffset += entryLength;
            }

            // Some Billy Hatcher textures have an oddity where the texture length is 16 more than what it
            // actually should be. This seems to only effect the last texture of a GVM, and only some of them
            // are affected. In that case, we will "fix" the GVRs in question.
            needToFix = (entryOffset > source.Length);

            // Set the position of the stream to the end of the file
            source.Seek(0, SeekOrigin.End);
        }