예제 #1
0
        public NXTL ReadTextureList(ExtendedBinaryReader reader, long pos)
        {
            TextureList = new NXTL()
            {
                TextureListNode = new string(reader.ReadChars(4)),
                NodeLength      = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32(), false);
            TextureList.TextureCount = reader.ReadUInt32();
            uint textureListOffset = reader.ReadUInt32();

            reader.JumpTo(textureListOffset, false);

            for (int i = 0; i < TextureList.TextureCount; i++)
            {
                reader.JumpAhead(0x4);
                uint textureNameOffset = reader.ReadUInt32();
                long texturePos        = reader.BaseStream.Position; //Save Position
                reader.JumpTo(textureNameOffset, false);
                TEXFILE tex = new TEXFILE();
                tex.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(texturePos);
                tex.Filters = reader.ReadUInt32();
                reader.JumpAhead(0x8);
                TextureList.Textures.Add(tex);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(TextureList.NodeLength);
            return(TextureList);
        }
예제 #2
0
        public override void Load(ExtendedBinaryReader reader, bool keepOpen = false)
        {
            // Check if file has a signature
            string sig = reader.ReadSignature();

            if (sig == "STSC")
            { // Newer script format
                uint headerSize = reader.ReadUInt32();
                Version = reader.ReadUInt32();
                switch (Version)
                {
                case 4:     // Date A Live: Twin Edition Rio Reincarnation (PSV)
                    ScriptID = reader.ReadUInt16();
                    break;

                case 7:     // Date A Live: Rio Reincarnation (PC)
                    ScriptName = reader.ReadNullTerminatedString();
                    reader.JumpAhead((uint)(0x20 - (ScriptName.Length + 1)));
                    reader.JumpAhead(12);
                    ScriptID = reader.ReadUInt32();
                    break;
                }
            }
            else
            { // Older script format
                // Jump back as older scripts have much smaller headers
                reader.JumpBehind(4);
                ScriptID = reader.ReadUInt16();
            }
            // Stupid workaround to find the end of the code segment
            reader.Offset = (uint)reader.BaseStream.Length;
            while (true)
            {
                byte opcode = reader.ReadByte();

                if (opcode >= 0x94)
                {
                    throw new STSCDisassembleException(this,
                                                       $"Got opcode 0x{opcode:X2} at 0x{reader.BaseStream.Position - 1:X8} in \"{ScriptName}\"" +
                                                       " There is no opcodes larger than 0x93!");
                }

                // Check if its a known instruction
                if (STSCInstructions.DALRRInstructions[opcode] == null)
                {
                    throw new STSCDisassembleException(this,
                                                       $"Got opcode 0x{opcode:X2} at 0x{reader.BaseStream.Position - 1:X8} in \"{ScriptName}\"" +
                                                       " This opcode is unknown!");
                }

                var instruction = STSCInstructions.DALRRInstructions[opcode].Read(reader);
                Instructions.Add(instruction);
                if (reader.BaseStream.Position >= reader.Offset)
                {
                    break;
                }
            }
        }
예제 #3
0
        // TODO
        protected void LoadShadowArchive(ExtendedBinaryReader reader)
        {
            reader.JumpAhead(0x4);                                 // Unknown, Seems to always be 0
            uint   fileSize   = reader.ReadUInt32();               // File Size - 0xC
            uint   magic      = reader.ReadUInt32();               // Magic
            string ONEVersion = reader.ReadNullTerminatedString(); // Gets the version String

            reader.FixPadding();                                   // Aligns the reader

            uint fileCount = reader.ReadUInt32();                  // File Count

            reader.JumpAhead(0x38 * 2 + 0x20);                     // Jump to the third/first entry
            bool isVersion6     = ONEVersion == "ONE Ver 0.60";    // Checks if its version is 0.60
            int  fileNameLength = isVersion6 ? 0x2C : 0x20;        // The max file name size

            // Read File List
            var files = new FileEntry[FileEntryCount];

            for (int i = 0; i < fileCount; i++)
            {
                var entry = new FileEntry();
                entry.FileName = reader.ReadSignature(
                    fileNameLength).Replace("\0", string.Empty);

                entry.UncompressedSize = reader.ReadUInt32();
                entry.DataOffset       = reader.ReadUInt32();
                reader.JumpAhead(4); // Unknown, Seems to always be 1

                if (!isVersion6)
                {
                    reader.JumpAhead(0xC); // Unknown, Seems to always be 0
                }
                files[i] = entry;
            }

            // Read File Data
            if (files.Length > 0)
            {
                reader.JumpTo(files[0].DataOffset + 0xC);
                for (int i = 0; i < fileCount; ++i)
                {
                    // Compute the file's data length
                    files[i].DataLength = ((i == fileCount - 1) ?
                                           fileSize + 0xC : files[i + 1].DataOffset) - files[i].DataOffset;

                    var file = new ArchiveFile()
                    {
                        Name = files[i].FileName,
                        Data = reader.ReadBytes(
                            (int)files[i].DataLength) // TODO: Decompress file
                    };
                    Data.Add(file);
                }
            }
        }
예제 #4
0
        public override void Load(Stream fileStream)
        {
            ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream)
            {
                Offset = 0x20
            };
            long pos = 0;

            // NINJA INFO [N*IF]
            InfoList = new NXIF()
            {
                HeaderInfoNode = new string(reader.ReadChars(4)),
                NodeLength     = reader.ReadUInt32(),
                NodeCount      = reader.ReadUInt32()
            };

            reader.JumpTo(InfoList.NodeLength + 8);

            for (int i = 0; i < InfoList.NodeCount; i++)
            {
                string nodeName   = new string(reader.ReadChars(4));
                uint   nodeLength = reader.ReadUInt32();
                reader.JumpBehind(8);
                switch (nodeName)
                {
                case "NXTL":
                case "NZTL":
                    // NINJA TEXTURE LIST [N*TL]
                    TextureList = ReadTextureList(reader, pos);
                    break;

                case "NXEF":
                    // NINJA EFFECTS [N*EF]
                    EffectList = ReadEffectList(reader, pos);
                    break;

                case "NXNN":
                    // NINJA NODE NAMES [N*NN]
                    NodeTree = ReadNodeNames(reader, pos);
                    break;

                case "NXOB":
                case "NZOB":
                    ObjectList = ReadNodes(reader, pos);
                    break;

                default:
                    reader.JumpAhead(8);
                    reader.JumpAhead(nodeLength);
                    Console.WriteLine($"Block {nodeName} Not Implemented!");
                    break;
                }
            }
        }
예제 #5
0
        public override void Load(Stream fileStream)
        {
            ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream)
            {
                Offset = 0x20
            };
            long pos = 0;

            NinjaInfo = new NinjaInfo()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();
            uint NodeCount  = reader.ReadUInt32();
            uint Unknown1   = reader.ReadUInt32(); //Seems to always be 0x20 (at least in XN*s)?
            uint Unknown2   = reader.ReadUInt32(); //Footer Offset Table Start?
            uint Unknown3   = reader.ReadUInt32(); //Footer Offset Table Data Start?
            uint Unknown4   = reader.ReadUInt32(); //Footer Offset Table Length?
            uint Unknown5   = reader.ReadUInt32(); //Seems to always be 1 (at least in XN*s)?

            for (int i = 0; i < NodeCount; i++)
            {
                //Determine type of node to read
                string NextNodeName   = new string(reader.ReadChars(4));
                uint   NextNodeLength = reader.ReadUInt32();
                reader.JumpBehind(8);
                switch (NextNodeName)
                {
                case "NXTL":
                case "NZTL":
                    NinjaTextureList = ReadNinjaTextureList(reader, pos);
                    break;

                case "NXEF":
                    NinjaEffectList = ReadNinjaEffectList(reader, pos);
                    break;

                case "NXNN":
                    NinjaNodeNameList = ReadNinjaNodeNameList(reader, pos);
                    break;

                case "NXOB":
                case "NZOB":
                    NinjaObject = ReadNinjaObject(reader, pos);
                    break;

                default:
                    reader.JumpAhead(8);
                    reader.JumpAhead(NextNodeLength);
                    //Console.WriteLine($"Block {NextNodeName} Not Implemented!");
                    break;
                }
            }
        }
예제 #6
0
        public NXNN ReadNodeNames(ExtendedBinaryReader reader, long pos)
        {
            NodeTree = new NXNN()
            {
                TreeNode   = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32() + 4, false);
            var nodeCount = reader.ReadUInt32();

            reader.JumpTo(reader.ReadUInt32(), false);
            for (int i = 0; i < nodeCount; i++)
            {
                NodeTree node = new NodeTree();
                node.NodeIndex = reader.ReadUInt32();
                var  nameOffset = reader.ReadUInt32();
                long nodePos    = reader.BaseStream.Position; //Save Position
                reader.JumpTo(nameOffset, false);
                node.NodeName = reader.ReadNullTerminatedString();
                reader.JumpTo(nodePos);
                NodeTree.Nodes.Add(node);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(NodeTree.NodeLength);
            return(NodeTree);
        }
예제 #7
0
        public override void Load(Stream fileStream)
        {
            // Header
            var reader = new ExtendedBinaryReader(fileStream);

            // Apparently SEGA doesn't even do signature checking (try loading an AR in-game
            // with the first 0xC bytes set to 0, it works just fine), so why should we?
            reader.JumpAhead(0xC);
            Padding = reader.ReadUInt32();

            // Data
            while (fileStream.Position < fileStream.Length)
            {
                reader.Offset = (uint)fileStream.Position;

                uint   dataEndOffset   = reader.ReadUInt32();
                uint   dataLength      = reader.ReadUInt32();
                uint   dataStartOffset = reader.ReadUInt32();
                uint   unknown1        = reader.ReadUInt32();
                uint   unknown2        = reader.ReadUInt32();
                string name            = reader.ReadNullTerminatedString();

                reader.JumpTo(dataStartOffset, false);
                var data = reader.ReadBytes((int)dataLength);
                reader.JumpTo(dataEndOffset, false);

                var file = new ArchiveFile()
                {
                    Name = name,
                    Data = data
                };
                Data.Add(file);
            }
        }
예제 #8
0
        /// <summary>
        /// Load file from Stream
        /// </summary>
        /// <param name="stream">The stream to read data from</param>
        /// <param name="autoDecompress">Automatically check for full file compression</param>
        /// <param name="keepOpen">Should the stream be kept open?</param>
        public virtual void Load(Stream stream, bool autoDecompress = true, bool keepOpen = false)
        {
            var reader = new ExtendedBinaryReader(stream);

            if (autoDecompress)
            {
                // Decompress Zlib stream
                if (reader.PeekSignature() == "ZLIB")
                {
                    // Skip ZLIB Header
                    reader.JumpAhead(14);
                    // Decompress stream
                    using (var deflate = new DeflateStream(reader.BaseStream, CompressionMode.Decompress, false))
                        reader.SetStream(deflate.CacheStream());
                    // Set Endianness of the reader
                    reader.SetEndian(UseBigEndian);
                    // Parse file
                    Load(reader);
                    return;
                }
            }
            // Set Endianness of the reader
            reader.SetEndian(UseBigEndian);
            // Parse File
            Load(reader, keepOpen);
        }
        // Methods
        public static void Read(HavokFile h, ExtendedBinaryReader reader)
        {
            // Header
            reader.JumpAhead(0x10);

            // A lot of this was gathered from the Max Havok exporter.
            byte bytesInPointer = reader.ReadByte();

            reader.IsBigEndian = !reader.ReadBoolean();
            byte reusePaddingOpt   = reader.ReadByte();
            byte emptyBaseClassOpt = reader.ReadByte();

            // We jump around a lot here, but there's not really a much cleaner way to do it.
            reader.JumpTo(8, true);
            h.UserTag      = reader.ReadUInt32();
            h.ClassVersion = reader.ReadInt32();
            reader.JumpAhead(4);

            uint  sectionsCount = reader.ReadUInt32();
            uint  unknown1      = reader.ReadUInt32();
            ulong padding1      = reader.ReadUInt64();

            uint unknown2 = reader.ReadUInt32();

            h.ContentsVersion = reader.ReadNullTerminatedString();
            reader.JumpAhead(9); // Seems to be padding

            // Sections
            for (uint i = 0; i < sectionsCount; ++i)
            {
                string sectionName = new string(reader.ReadChars(0x10));
                sectionName = sectionName.Replace("\0", string.Empty);

                // TODO
                reader.JumpAhead(0x20);
            }

            // Padding Checks
            if (padding1 != 0)
            {
                Console.WriteLine($"WARNING: Padding1 != 0 ({padding1})");
            }

            // TODO
            throw new NotImplementedException();
        }
예제 #10
0
 public void Load(ExtendedBinaryReader reader)
 {
     SourceX = reader.ReadSingle();
     SourceY = reader.ReadSingle();
     DestinX = reader.ReadSingle();
     DestinY = reader.ReadSingle();
     reader.JumpAhead(0x30); // Unknown
 }
예제 #11
0
 public void Load(ExtendedBinaryReader reader)
 {
     TextureFullPath = reader.ReadSignature(0x200).Trim('\0');
     TextureFileName = reader.ReadSignature(0x080).Trim('\0');
     TextureWidth    = reader.ReadInt32();
     TextureHeight   = reader.ReadInt32();
     reader.JumpAhead(0x84); // Unknown
 }
예제 #12
0
        public override void Load(Stream fileStream)
        {
            ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream)
            {
                Offset = 0x20
            };

            reader.JumpAhead(16);
            reader.JumpTo(reader.ReadUInt32(), false);
            reader.JumpAhead(8);
            var offsetCount = reader.ReadUInt32();

            reader.JumpAhead(4);
            for (int i = 0; i < offsetCount; i++)
            {
                Offsets.Add(reader.ReadUInt32());
                Offsets[i] = Offsets[i] + 0x20;
            }
        }
예제 #13
0
        public override void Load(Stream fileStream)
        {
            var reader = new ExtendedBinaryReader(fileStream, false);

            reader.JumpAhead(4); // CRC32?
            int fileCount = reader.ReadInt32();

            var fileEntries = new List <FileEntry>();

            for (int i = 0; i < fileCount; ++i)
            {
                var fileEntry = new FileEntry();
                fileEntry.FileName             = reader.ReadSignature(0x40).Replace("\0", "");
                fileEntry.DataUncompressedSize = reader.ReadUInt32();
                fileEntry.DataSize             = reader.ReadUInt32();
                fileEntry.DataOffset           = reader.ReadUInt32();
                fileEntry.Compressed           = reader.ReadByte() == 1;
                reader.JumpAhead(3); // Other Attributes?
                fileEntries.Add(fileEntry);
            }

            foreach (var fileEntry in fileEntries)
            {
                reader.JumpTo(fileEntry.DataOffset);

                byte[] data = null;
                if (fileEntry.Compressed)
                {
                    data = ReadAndDecompress(reader);
                }
                else
                {
                    data = reader.ReadBytes((int)fileEntry.DataUncompressedSize);
                }

                // Adds the File
                Data.Add(new ArchiveFile()
                {
                    Name = fileEntry.FileName,
                    Data = data
                });
            }
        }
예제 #14
0
        // Methods
        public override void Read(ExtendedBinaryReader reader)
        {
            // BINA Header
            string sig = reader.ReadSignature(4);

            if (sig != Signature)
            {
                throw new InvalidSignatureException(Signature, sig);
            }

            // Version String
            string verString = reader.ReadSignature(3);

            if (!ushort.TryParse(verString, out Version))
            {
                Console.WriteLine(
                    "WARNING: BINA header version was invalid! ({0})",
                    verString);
            }

            reader.IsBigEndian = IsBigEndian =
                (reader.ReadChar() == BigEndianFlag);
            FileSize = reader.ReadUInt32();

            ushort nodeCount = reader.ReadUInt16();
            ushort unknown1  = reader.ReadUInt16(); // Always 0? Padding??

            // TODO: Read Nodes Properly
            if (nodeCount < 1)
            {
                return;
            }

            // DATA Header
            string dataSig = reader.ReadSignature();

            if (dataSig != DataSignature)
            {
                throw new InvalidSignatureException(DataSignature, dataSig);
            }

            DataLength        = reader.ReadUInt32();
            StringTableOffset = reader.ReadUInt32();
            StringTableLength = reader.ReadUInt32();
            FinalTableLength  = reader.ReadUInt32();

            // Additional data
            ushort additionalDataLength = reader.ReadUInt16();
            ushort unknown3             = reader.ReadUInt16(); // Padding?

            reader.JumpAhead(additionalDataLength);
            reader.Offset = (uint)reader.BaseStream.Position;
        }
예제 #15
0
            public void Load(ExtendedBinaryReader reader)
            {
                LayerName = reader.ReadSignature(0x20);
                uint unknown20 = reader.ReadUInt32();

                TextureID = reader.ReadInt32();
                uint Offset    = reader.ReadUInt32();
                uint unknown2C = reader.ReadUInt32();

                //
                uint oldpos = (uint)reader.GetPosition();

                reader.JumpTo(Offset);

                reader.JumpAhead(0x164);
                LayerOffX = reader.ReadSingle();
                LayerOffY = reader.ReadSingle();
                reader.JumpAhead(4);
                LayerWidth  = reader.ReadSingle();
                LayerHeight = reader.ReadSingle();

                reader.JumpAhead(0x88); // Unknown

                /*
                 * Top Left
                 * Top Right
                 * Bottom Left
                 * Bottom Right
                 */

                for (int i = 0; i < 4; ++i)
                {
                    Verts.Add(new MAVert(reader));
                }

                reader.JumpTo(oldpos);

                reader.JumpAhead(0x84); // Unknown
            }
예제 #16
0
        public static byte[] ReadAndDecompress(ExtendedBinaryReader reader)
        {
            var  stream           = new MemoryStream();
            uint decompressedSize = reader.ReadUInt32();
            uint compressedSize   = reader.ReadUInt32();
            byte copyByte         = reader.ReadByte();

            reader.JumpAhead(3);
            uint dataStartOffset = (uint)reader.BaseStream.Position;

            while (stream.Position < decompressedSize)
            {
                byte b = reader.ReadByte();

                if (b == copyByte)
                {
                    byte returnByte = reader.ReadByte();

                    if (returnByte == copyByte)
                    {
                        stream.WriteByte(returnByte);
                        continue;
                    }

                    if (returnByte >= copyByte)
                    {
                        returnByte--;
                    }

                    uint offset          = (uint)stream.Position - returnByte;
                    byte length          = reader.ReadByte();
                    uint currentPosition = (uint)stream.Position;

                    stream.Position = offset;
                    byte[] buffer = new byte[length];
                    stream.Read(buffer, 0, length);
                    stream.Position = currentPosition;
                    stream.Write(buffer, 0, length);
                }
                else
                {
                    stream.WriteByte(b);
                }
            }
            return(stream.ToArray());
        }
예제 #17
0
        // Methods
        public override void Load(Stream fileStream)
        {
            var reader = new ExtendedBinaryReader(fileStream, Encoding.ASCII, false);

            // Checks the Magic
            reader.JumpAhead(0x8);          // Jump to Magic
            Magic = reader.ReadUInt32();    // Magic
            reader.JumpBehind(0xC);         // Jump back to the start

            if (Magic == (uint)Magics.Shadow6 || Magic == (uint)Magics.Shadow5)
            {
                LoadShadowArchive(reader);  // Shadow the Hedgehog Archive
            }
            else
            {
                LoadHeroesArchive(reader);  // Sonic Heroes Archive
            }
        }
예제 #18
0
        public NXEF ReadEffectList(ExtendedBinaryReader reader, long pos)
        {
            EffectList = new NXEF()
            {
                EffectNode = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32() + 4, false);
            var effectTypeCount  = reader.ReadUInt32();
            var effectTypeOffset = reader.ReadUInt32();
            var techiqueCount    = reader.ReadUInt32();
            var techniqueOffset  = reader.ReadUInt32();

            reader.JumpTo(effectTypeOffset, false);
            for (int i = 0; i < effectTypeCount; i++)
            {
                EFFFILE effFile = new EFFFILE();
                effFile.Type = reader.ReadUInt32();
                var  jumpPoint = reader.ReadUInt32();
                long effectPos = reader.BaseStream.Position; //Save Position
                reader.JumpTo(jumpPoint, false);
                effFile.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(effectPos);
                EffectList.Effects.Add(effFile);
            }
            reader.JumpTo(techniqueOffset, false);
            for (int i = 0; i < techiqueCount; i++)
            {
                TECHNAME tech = new TECHNAME();
                tech.Type   = reader.ReadUInt32();
                tech.NodeID = reader.ReadUInt32();
                var  jumpPoint = reader.ReadUInt32();
                long techPos   = reader.BaseStream.Position; //Save Position
                reader.JumpTo(jumpPoint, false);
                tech.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(techPos);
                EffectList.Techs.Add(tech);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(EffectList.NodeLength);
            return(EffectList);
        }
예제 #19
0
        public NinjaTextureList ReadNinjaTextureList(ExtendedBinaryReader reader, long pos)
        {
            NinjaTextureList = new NinjaTextureList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint TextureCount      = reader.ReadUInt32();
            uint TextureListOffset = reader.ReadUInt32();

            reader.JumpTo(TextureListOffset, false);

            for (int i = 0; i < TextureCount; i++)
            {
                uint Unknown1          = reader.ReadUInt32();        //Seems to always be 0 (at least in XN*s)? (Padding?)
                uint TextureNameOffset = reader.ReadUInt32();
                long currentPos        = reader.BaseStream.Position; //Save Position
                reader.JumpTo(TextureNameOffset, false);
                NinjaTextureFile TextureFile = new NinjaTextureFile()
                {
                    TextureName = reader.ReadNullTerminatedString()
                };
                reader.JumpTo(currentPos, true);
                TextureFile.Filters = reader.ReadUInt32();
                uint Unknown2 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
                uint Unknown3 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
                NinjaTextureList.TextureFiles.Add(TextureFile);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaTextureList);
        }
예제 #20
0
        public NinjaNodeNameList ReadNinjaNodeNameList(ExtendedBinaryReader reader, long pos)
        {
            NinjaNodeNameList = new NinjaNodeNameList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint Unknown1        = reader.ReadUInt32(); //Padding?
            uint NodeTableCount  = reader.ReadUInt32();
            uint NodeTableOffset = reader.ReadUInt32();

            reader.JumpTo(NodeTableOffset, false);

            for (int i = 0; i < NodeTableCount; i++)
            {
                NinjaNodeName NodeName = new NinjaNodeName()
                {
                    ID = reader.ReadUInt32()
                };
                uint NodeNameIndex = reader.ReadUInt32();
                long currentPos    = reader.BaseStream.Position; //Save Position
                reader.JumpTo(NodeNameIndex, false);
                NodeName.Name = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaNodeNameList.NinjaNodeNames.Add(NodeName);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaNodeNameList);
        }
예제 #21
0
        public NXOB ReadNodes(ExtendedBinaryReader reader, long pos)
        {
            /*
             * Sonic 4 Decompilation Ref
             * public NNS_NODE( AppMain.NNS_NODE node )
             * {
             *  this.fType = node.fType;
             *  this.iMatrix = node.iMatrix;
             *  this.iParent = node.iParent;
             *  this.iChild = node.iChild;
             *  this.iSibling = node.iSibling;
             *  this.Translation.Assign( node.Translation );
             *  this.Rotation = node.Rotation;
             *  this.Scaling.Assign( node.Scaling );
             *  this.InvInitMtx.Assign( node.InvInitMtx );
             *  this.Center.Assign( node.Center );
             *  this.Radius = node.Radius;
             *  this.User = node.User;
             *  this.SIIKBoneLength = node.SIIKBoneLength;
             *  this.BoundingBoxY = node.BoundingBoxY;
             *  this.BoundingBoxZ = node.BoundingBoxZ;
             * }
             */
            ObjectList = new NXOB()
            {
                ObjectList = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32(), false);
            reader.JumpAhead(0x10);

            //Variable Names Copy & Pasted from MaxScript
            var TexElmTotal  = reader.ReadUInt32();
            var TexElmOffset = reader.ReadUInt32();

            var VertGroupTotal  = reader.ReadUInt32();
            var VertGroupOffset = reader.ReadUInt32();

            var PolyElmTotal  = reader.ReadUInt32();
            var PolyElmOffset = reader.ReadUInt32();

            //Nodes
            var NodeTotal     = reader.ReadUInt32();
            var UnknownCount1 = reader.ReadUInt32(); //Count of SOMETHING?
            var NodeOffset    = reader.ReadUInt32();

            var UnknownCount2 = reader.ReadUInt32(); //MaxScript calls this NodeTotal, but I'm sure what they call BoneTotal is actually NodeTotal? Seems to be a Count of something
            var LinkTotal     = reader.ReadUInt32();
            var LinkOffset    = reader.ReadUInt32();
            var UnknownCount3 = reader.ReadUInt32(); //Count of SOMETHING?

            //NNS_NODE
            reader.JumpTo(NodeOffset, false);
            for (int i = 0; i < NodeTotal; i++)
            {
                Node node = new Node();
                node.NODE_TYPE    = reader.ReadUInt32();
                node.NODE_MATRIX  = reader.ReadUInt16();
                node.NODE_PARENT  = reader.ReadUInt16();
                node.NODE_CHILD   = reader.ReadUInt16();
                node.NODE_SIBLING = reader.ReadUInt16();

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_TRN.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_ROT.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_SCL.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 16; n++)
                {
                    node.NODE_INVINIT_MTX.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_CENTER.Add(reader.ReadSingle());
                }

                node.NODE_RADIUS = reader.ReadSingle();
                node.NODE_USER   = reader.ReadUInt32();
                node.NODE_RSV0   = reader.ReadUInt32();
                node.NODE_RSV1   = reader.ReadUInt32();
                node.NODE_RSV2   = reader.ReadUInt32();
                ObjectList.Nodes.Add(node);
            }

            reader.JumpTo(TexElmOffset, false);
            var Unknown1 = reader.ReadUInt32(); //Assume this is a count???

            reader.JumpTo(reader.ReadUInt32(), false);

            return(ObjectList);
        }
예제 #22
0
        public NinjaEffectList ReadNinjaEffectList(ExtendedBinaryReader reader, long pos)
        {
            NinjaEffectList = new NinjaEffectList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint Unknown1           = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
            uint EffectTypeCount    = reader.ReadUInt32();
            uint EffectTypeOffset   = reader.ReadUInt32();
            uint TechniqueCount     = reader.ReadUInt32();
            uint TechniqueOffset    = reader.ReadUInt32();
            uint TechniqueIDXCount  = reader.ReadUInt32();
            uint TechniqueIDXOffset = reader.ReadUInt32();

            //Effect Files
            reader.JumpTo(EffectTypeOffset, false);
            for (int i = 0; i < EffectTypeCount; i++)
            {
                NinjaEffectFile EffectFile = new NinjaEffectFile()
                {
                    Type = reader.ReadUInt32()
                };
                uint EffectFilenameOffset = reader.ReadUInt32();
                long currentPos           = reader.BaseStream.Position; //Save Position
                reader.JumpTo(EffectFilenameOffset, false);
                EffectFile.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaEffectList.EffectFiles.Add(EffectFile);
            }

            //Effect List
            reader.JumpTo(TechniqueOffset, false);
            for (int i = 0; i < TechniqueCount; i++)
            {
                NinjaEffectTechnique Technique = new NinjaEffectTechnique()
                {
                    Type = reader.ReadUInt32(),
                    ID   = reader.ReadUInt32()
                };
                uint TechniqueNameOffset = reader.ReadUInt32();
                long currentPos          = reader.BaseStream.Position; //Save Position
                reader.JumpTo(TechniqueNameOffset, false);
                Technique.TechniqueName = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaEffectList.Techniques.Add(Technique);
            }

            //Technique IDX (not sure what this is for)
            reader.JumpTo(TechniqueIDXOffset, false);
            for (int i = 0; i < TechniqueIDXCount; i++)
            {
                NinjaEffectList.TechniqueIDX.Add(reader.ReadUInt16());
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaEffectList);
        }
예제 #23
0
        public NinjaObject ReadNinjaObject(ExtendedBinaryReader reader, long pos)
        {
            NinjaObject = new NinjaObject()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            NinjaObject.ObjectCenter = reader.ReadVector3();
            NinjaObject.ObjectRadius = reader.ReadSingle();
            uint ObjectMaterialCount   = reader.ReadUInt32();
            uint ObjectMaterialOffset  = reader.ReadUInt32();
            uint ObjectVTXCount        = reader.ReadUInt32();
            uint ObjectVTXOffset       = reader.ReadUInt32();
            uint ObjectPrimitiveCount  = reader.ReadUInt32();
            uint ObjectPrimitiveOffset = reader.ReadUInt32();
            uint ObjectNodeCount       = reader.ReadUInt32();

            NinjaObject.ObjectMaxNodeDepth = reader.ReadUInt32();
            uint ObjectNodeOffset = reader.ReadUInt32();

            NinjaObject.ObjectMTXPAL = reader.ReadUInt32();
            uint ObjectSubObjectCount  = reader.ReadUInt32();
            uint ObjectSubObjectOffset = reader.ReadUInt32();

            NinjaObject.ObjectTextureCount = reader.ReadUInt32();

            //Materials
            reader.JumpTo(ObjectMaterialOffset, false);
            for (int i = 0; i < ObjectMaterialCount; i++)
            {
                //TO-DO: Figure out how all this fits together
                NinjaObjectMaterial ObjectMaterial = new NinjaObjectMaterial()
                {
                    MaterialType = reader.ReadUInt32()
                };
                uint MaterialOffset = reader.ReadUInt32();
                long currentPos     = reader.BaseStream.Position; //Save Position
                reader.JumpTo(MaterialOffset, false);

                ObjectMaterial.MaterialFlags = reader.ReadUInt32();
                ObjectMaterial.User          = reader.ReadUInt32();
                uint MaterialColourOffset  = reader.ReadUInt32();
                uint MaterialLogicOffset   = reader.ReadUInt32();
                uint MaterialTexDescOffset = reader.ReadUInt32();

                reader.JumpTo(MaterialColourOffset, false);
                ObjectMaterial.MaterialDiffuse  = reader.ReadVector4();
                ObjectMaterial.MaterialAmbient  = reader.ReadVector4();
                ObjectMaterial.MaterialSpecular = reader.ReadVector4();
                ObjectMaterial.MaterialEmissive = reader.ReadVector4();
                ObjectMaterial.MaterialPower    = reader.ReadSingle();

                reader.JumpTo(MaterialLogicOffset, false);
                ObjectMaterial.MaterialBlendenable   = reader.ReadUInt32();
                ObjectMaterial.MaterialSRCBlend      = reader.ReadUInt32();
                ObjectMaterial.MaterialDSTBlend      = reader.ReadUInt32();
                ObjectMaterial.MaterialBlendFactor   = reader.ReadUInt32();
                ObjectMaterial.MaterialBlendOP       = reader.ReadUInt32();
                ObjectMaterial.MaterialLogicOP       = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaEnable   = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaFunction = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaRef      = reader.ReadUInt32();
                ObjectMaterial.MaterialZCompenable   = reader.ReadUInt32();
                ObjectMaterial.MaterialZFunction     = reader.ReadUInt32();
                ObjectMaterial.MaterialZUpdateEnable = reader.ReadUInt32();

                reader.JumpTo(MaterialTexDescOffset, false);
                ObjectMaterial.TextureTexMapType  = reader.ReadUInt32();
                ObjectMaterial.TextureID          = reader.ReadUInt32();
                ObjectMaterial.TextureOffset      = reader.ReadVector2();
                ObjectMaterial.TextureBlend       = reader.ReadSingle();
                ObjectMaterial.TextureInfoPTR     = reader.ReadUInt32();
                ObjectMaterial.TextureMinFilter   = reader.ReadUInt32();
                ObjectMaterial.TextureMagFilter   = reader.ReadUInt32();
                ObjectMaterial.TextureMipMapBias  = reader.ReadSingle();
                ObjectMaterial.TextureMaxMipLevel = reader.ReadUInt32();

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectMaterialList.Add(ObjectMaterial);
            }

            //Vertexes
            reader.JumpTo(ObjectVTXOffset, false);
            for (int i = 0; i < ObjectVTXCount; i++)
            {
                NinjaObjectVertex ObjectVertex = new NinjaObjectVertex()
                {
                    Type = reader.ReadUInt32()
                };
                uint VTXOffset  = reader.ReadUInt32();
                long currentPos = reader.BaseStream.Position; //Save Position

                reader.JumpTo(VTXOffset, false);
                ObjectVertex.VTXFormat = reader.ReadUInt32();
                ObjectVertex.VTXFVF    = reader.ReadUInt32();
                ObjectVertex.VTXSize   = reader.ReadUInt32();
                uint VTXNumber     = reader.ReadUInt32();
                uint VTXListOffset = reader.ReadUInt32();
                ObjectVertex.VTXBlendNum = reader.ReadUInt32();
                uint VTXMTXOffset = reader.ReadUInt32();
                ObjectVertex.VTXHDRCommon = reader.ReadUInt32();
                ObjectVertex.VTXHDRData   = reader.ReadUInt32();
                ObjectVertex.VTXHDRLock   = reader.ReadUInt32();

                reader.JumpTo(VTXListOffset, false);
                for (int v = 0; v < VTXNumber; v++)
                {
                    NinjaObjectVertexList Vertex = new NinjaObjectVertexList();
                    switch (ObjectVertex.VTXSize)
                    {
                    //Any ones other than 52 & 76 are probably wrong here, as they're not in the XTO and are instead based on the MaxScript
                    //This is such a mess
                    case 20:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 24:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 28:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 32:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 36:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 44:
                        Vertex.Position  = reader.ReadVector3();
                        Vertex.Normals   = reader.ReadVector3();
                        Vertex.RGBA8888  = reader.ReadBytes(4);
                        Vertex.ST0       = reader.ReadVector2();
                        Vertex.UnknownV2 = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 48:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 52:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 60:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 72:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 76:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    default:
                        Console.WriteLine($"Vertex Size of {ObjectVertex.VTXSize} not handled!");
                        continue;
                    }
                }

                if (VTXMTXOffset != 0)
                {
                    reader.JumpTo(VTXMTXOffset, false);
                    ObjectVertex.VTXMTX = reader.ReadInt32();
                }

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectVertexList.Add(ObjectVertex);
            }

            reader.JumpTo(ObjectPrimitiveOffset, false);
            for (int i = 0; i < ObjectPrimitiveCount; i++)
            {
                NinjaObjectPrimitive ObjectPrimitive = new NinjaObjectPrimitive()
                {
                    Type = reader.ReadUInt32()
                };
                uint PrimitiveListOffset = reader.ReadUInt32();
                long currentPos          = reader.BaseStream.Position; //Save Position

                reader.JumpTo(PrimitiveListOffset, false);
                ObjectPrimitive.Format = reader.ReadUInt32();
                ObjectPrimitive.Index  = reader.ReadUInt32();
                ObjectPrimitive.Strip  = reader.ReadUInt32();
                uint LengthOffset = reader.ReadUInt32();
                uint IndexOffset  = reader.ReadUInt32();
                ObjectPrimitive.IndexBuf = reader.ReadUInt32();

                reader.JumpTo(LengthOffset, false);
                ObjectPrimitive.IndexLength = reader.ReadUInt16(); //May be the same as Index all the time???

                reader.JumpTo(IndexOffset, false);
                for (int v = 0; v < ObjectPrimitive.Index; v++)
                {
                    ObjectPrimitive.VertexIndexList.Add(reader.ReadUInt16());
                }

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectPrimitiveList.Add(ObjectPrimitive);
            }

            reader.JumpTo(ObjectNodeOffset, false);
            for (int i = 0; i < ObjectNodeCount; i++)
            {
                NinjaObjectNodeList Node = new NinjaObjectNodeList()
                {
                    Type      = reader.ReadUInt32(),
                    Matrix    = reader.ReadUInt16(),
                    Parent    = reader.ReadUInt16(),
                    Child     = reader.ReadUInt16(),
                    Sibling   = reader.ReadUInt16(),
                    Transform = reader.ReadVector3(),
                    Rotation  = reader.ReadVector3(),
                    Scale     = reader.ReadVector3()
                };
                for (int v = 0; v < 16; v++)
                {
                    Node.Invinit.Add(reader.ReadSingle());
                }
                Node.Center = reader.ReadVector3();
                Node.User   = reader.ReadUInt32();
                Node.RSV0   = reader.ReadUInt32();
                Node.RSV1   = reader.ReadUInt32();
                Node.RSV2   = reader.ReadUInt32();
                reader.JumpAhead(0x4);
                NinjaObject.ObjectNodeList.Add(Node);
            }

            reader.JumpTo(ObjectSubObjectOffset, false);
            for (int i = 0; i < ObjectSubObjectCount; i++)
            {
                uint Type           = reader.ReadUInt32();
                uint NMSST          = reader.ReadUInt32();
                uint MSSTOffset     = reader.ReadUInt32();
                uint Textures       = reader.ReadUInt32();
                uint TexturesOffset = reader.ReadUInt32();
                long currentPos     = reader.BaseStream.Position; //Save Position

                reader.JumpTo(MSSTOffset, false);
                for (int v = 0; v < NMSST; v++)
                {
                    NinjaObjectSubObject SubObject = new NinjaObjectSubObject()
                    {
                        Center     = reader.ReadVector3(),
                        Radius     = reader.ReadSingle(),
                        Node       = reader.ReadUInt32(),
                        Matrix     = reader.ReadUInt32(),
                        Material   = reader.ReadUInt32(),
                        VertexList = reader.ReadUInt32(),
                        PrimList   = reader.ReadUInt32(),
                        ShaderList = reader.ReadUInt32()
                    };
                    NinjaObject.ObjectSubObjectList.Add(SubObject);
                }

                reader.JumpTo(currentPos, true);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaObject);
        }
예제 #24
0
        // Methods
        public static List <SetObject> Read(ExtendedBinaryReader reader,
                                            Dictionary <string, SetObjectType> objectTemplates, SOBJType type)
        {
            var objs = new List <SetObject>();

            // SOBJ Header
            var sig = reader.ReadChars(4);

            if (!reader.IsBigEndian)
            {
                Array.Reverse(sig);
            }

            string sigString = new string(sig);

            if (sigString != Signature)
            {
                throw new InvalidSignatureException(Signature, sigString);
            }

            uint unknown1             = reader.ReadUInt32();
            uint objTypeCount         = reader.ReadUInt32();
            uint objTypeOffsetsOffset = reader.ReadUInt32();

            reader.JumpAhead(4);
            uint objOffsetsOffset = reader.ReadUInt32();
            uint objCount         = reader.ReadUInt32();
            uint unknown2         = reader.ReadUInt32(); // Probably just padding

            if (unknown2 != 0)
            {
                Console.WriteLine("WARNING: Unknown2 != 0! ({0})", unknown2);
            }

            uint transformsCount = reader.ReadUInt32();

            // Object Offsets
            var objOffsets = new uint[objCount];

            reader.JumpTo(objOffsetsOffset, false);

            for (uint i = 0; i < objCount; ++i)
            {
                objOffsets[i] = reader.ReadUInt32();
                objs.Add(new SetObject());
            }

            // Object Types
            reader.JumpTo(objTypeOffsetsOffset, false);

            for (uint i = 0; i < objTypeCount; ++i)
            {
                // Object Type
                string objName          = reader.GetString();
                uint   objOfTypeCount   = reader.ReadUInt32();
                uint   objIndicesOffset = reader.ReadUInt32();
                long   curTypePos       = reader.BaseStream.Position;

                // Objects
                reader.JumpTo(objIndicesOffset, false);

                for (uint i2 = 0; i2 < objOfTypeCount; ++i2)
                {
                    ushort objIndex = reader.ReadUInt16();
                    long   curPos   = reader.BaseStream.Position;
                    var    obj      = new SetObject();

                    // We do this check here so we can print an offset that's actually helpful
                    if (!objectTemplates.ContainsKey(objName))
                    {
                        Console.WriteLine("{0} \"{1}\" (Offset: 0x{2:X})! Skipping this object...",
                                          "WARNING: No object template exists for object type",
                                          objName, (objOffsets[objIndex] + reader.Offset));

                        // Object Data without a template
                        reader.JumpTo(objOffsets[objIndex], false);
                        obj = ReadObject(reader,
                                         null, objName, type);
                    }
                    else
                    {
                        // Object Data with a template
                        reader.JumpTo(objOffsets[objIndex], false);
                        obj = ReadObject(reader,
                                         objectTemplates[objName], objName, type);
                    }

                    objs[objIndex]             = obj;
                    reader.BaseStream.Position = curPos;
                }

                reader.BaseStream.Position = curTypePos;
            }
            return(objs);
        }
예제 #25
0
        // Methods
        public override void Read(ExtendedBinaryReader reader)
        {
            // We need to know whether the file is big or little endian first
            var pos = reader.BaseStream.Position;

            reader.BaseStream.Position += 0x14;
            reader.IsBigEndian          = false;

            // Version String/Endian Flag
            uint   binaFlags = reader.ReadUInt32();
            string verString = "xyz"; // Just 3 chars that would fail ushort.TryParse

            unsafe
            {
                // Endian Flag
                reader.IsBigEndian = IsBigEndian = ((char)(
                                                        (binaFlags & 0xFF000000) >> 24) == BigEndianFlag);

                // Quick way to grab the last 3 bytes from binaFlags (which
                // are chars) and stuff them into a string we can then
                // safely parse into a ushort via ushort.TryParse
                fixed(char *vp = verString)
                {
                    *vp = (char)((binaFlags & 0xFF0000) >> 16);
                    vp[1] = (char)((binaFlags & 0xFF00) >> 16);
                    vp[2] = (char)(binaFlags & 0xFF);
                }
            }

            if (!ushort.TryParse(verString, out Version))
            {
                Console.WriteLine(
                    "WARNING: BINA header version was invalid! ({0})",
                    verString);
            }

            // Alright, cool, *NOW* we can read the rest of the header
            reader.BaseStream.Position = pos;

            // Header
            FileSize         = reader.ReadUInt32();
            FinalTableOffset = reader.ReadUInt32();
            FinalTableLength = reader.ReadUInt32();

            uint unknown1 = reader.ReadUInt32();

            if (unknown1 != 0)
            {
                Console.WriteLine($"WARNING: Unknown1 is not zero! ({unknown1})");
            }

            ushort unknownFlag1 = reader.ReadUInt16();

            if (unknownFlag1 != 0)
            {
                Console.WriteLine($"WARNING: UnknownFlag1 is not zero! ({unknownFlag1})");
            }

            IsFooterMagicPresent = (reader.ReadUInt16() == 1); // FooterNodeCount?
            reader.JumpAhead(4);

            // BINA Signature
            string sig = reader.ReadSignature(4);

            if (sig != Signature)
            {
                throw new InvalidSignatureException(Signature, sig);
            }

            // TODO: Find out what this is. Maybe additional data length?
            uint unknown2 = reader.ReadUInt32();

            if (unknown2 != 0)
            {
                Console.WriteLine($"WARNING: Unknown2 is not zero! ({unknown2})");
            }

            reader.Offset = (uint)reader.BaseStream.Position;
        }
예제 #26
0
        public static byte[] DecompressLZ77(this byte[] compressed)
        {
            byte[] buffer = null;
            using (var reader = new ExtendedBinaryReader(new MemoryStream(compressed)))
            {
                int  position     = 0;
                long flagPosition = 0;
                if (reader.ReadSignature() == "LZ77")
                {
                    int uncompressedSize = reader.ReadInt32();
                    int lz77Step         = reader.ReadInt32();
                    int offset           = reader.ReadInt32();
                    flagPosition = reader.GetPosition();
                    reader.JumpTo(offset);
                    buffer = new byte[uncompressedSize];
                }

                int flagCount = 0;
                int flag      = 0;
                while (true)
                {
                    if (flagCount == 0)
                    {
                        if (flagPosition >= compressed.Length)
                        {
                            break;
                        }
                        if (flagPosition == reader.GetPosition())
                        {
                            reader.JumpAhead(1);
                        }
                        flag      = compressed[flagPosition++];
                        flagCount = 8;
                    }
                    if ((flag & 0x80) != 0)
                    {
                        if (reader.GetPosition() + 2 > compressed.Length)
                        {
                            break;
                        }
                        int backStep = reader.ReadByte();
                        int amount   = reader.ReadByte();
                        for (amount += 3; (amount--) != 0; position++)
                        {
                            if (position >= buffer.Length)
                            {
                                break;
                            }
                            buffer[position] = buffer[position - backStep];
                        }
                    }
                    else
                    {
                        if (position >= buffer.Length)
                        {
                            break;
                        }
                        buffer[position++] = reader.ReadByte();
                    }
                    flag <<= 1;
                    flagCount--;
                }
            }
            return(buffer);
        }
예제 #27
0
        // Methods
        public override void Load(Stream fileStream)
        {
            // Signature
            var reader = new ExtendedBinaryReader(
                fileStream, Encoding.ASCII, false);

            string sig = reader.ReadSignature(4);

            if (sig != Signature)
            {
                throw new InvalidSignatureException(Signature, sig);
            }

            // Header
            Header = new DDSHeader()
            {
                Size  = reader.ReadUInt32(),
                Flags = reader.ReadUInt32()
            };

            if (!Header.HasFlag(DDSHeader.FLAGS.CAPS) ||
                !Header.HasFlag(DDSHeader.FLAGS.WIDTH) ||
                !Header.HasFlag(DDSHeader.FLAGS.HEIGHT) ||
                !Header.HasFlag(DDSHeader.FLAGS.PIXEL_FORMAT))
            {
                throw new Exception(
                          "Could not load DDS file. Required header flags are missing!");
            }

            Height = reader.ReadUInt32();
            Width  = reader.ReadUInt32();

            Header.PitchOrLinearSize = reader.ReadUInt32();
            Header.Depth             = reader.ReadUInt32();
            Header.MipmapCount       = reader.ReadUInt32();

            reader.JumpAhead(44); // Skip past padding
            Header.PixelFormat = new DDSPixelFormat(reader);

            Header.Caps  = reader.ReadUInt32();
            Header.Caps2 = reader.ReadUInt32();
            Header.Caps3 = reader.ReadUInt32();
            Header.Caps4 = reader.ReadUInt32();

            reader.JumpTo(Header.Size + 4, true);

            // Depth
            uint depth = 1;

            if (Header.HasFlag(DDSHeader.FLAGS.DEPTH) &&
                Header.HasFlag(DDSHeader.CAPS2.VOLUME))
            {
                depth = Header.Depth;

                // TODO
                throw new NotImplementedException(
                          "Reading 3D textures from DDS files is not yet supported.");
            }
            else if (Header.HasFlag(DDSHeader.CAPS2.CUBEMAP))
            {
                depth = 6;

                // TODO
                throw new NotImplementedException(
                          "Reading DDS cubemaps is not yet supported.");
            }

            // MipMaps
            uint mipmapCount = 1;

            if (Header.HasFlag(DDSHeader.FLAGS.MIPMAP_COUNT) &&
                Header.HasFlag(DDSHeader.CAPS.MIPMAP))
            {
                mipmapCount = Header.MipmapCount;
            }

            MipmapCount = mipmapCount;

            // Caps
            if (!Header.HasFlag(DDSHeader.CAPS.TEXTURE))
            {
                throw new Exception(
                          "Could not load DDS file. Required CAPS flag is missing!");
            }
            // TODO

            // Caps2
            // TODO

            // DX10 Header/Pixel Format
            uint pixelsPerBlock = 16;
            byte blockSize;

            if (Header.PixelFormat.HasFlag(DDSPixelFormat.FLAGS.FOURCC))
            {
                switch ((DDSPixelFormat.FOURCCS)Header.PixelFormat.FourCC)
                {
                // DX10 Header
                case DDSPixelFormat.FOURCCS.DX10:
                {
                    var dx10Header = new DX10Header(reader);
                    depth = dx10Header.ArraySize;

                    switch ((DX10Header.DXGI_FORMATS)dx10Header.DXGIFormat)
                    {
                    // BC1
                    case DX10Header.DXGI_FORMATS.BC1_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC1_UNORM:
                        CompressionFormat = CompressionFormats.RGB_S3TC_DXT1_EXT;
                        blockSize         = 8;
                        break;

                    // BC3
                    case DX10Header.DXGI_FORMATS.BC3_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC3_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_S3TC_DXT3_EXT;
                        blockSize         = 16;
                        break;

                    // BC5
                    case DX10Header.DXGI_FORMATS.BC5_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC5_SNORM:
                    case DX10Header.DXGI_FORMATS.BC5_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_S3TC_DXT5_EXT;
                        blockSize         = 16;
                        break;

                    // BC7
                    case DX10Header.DXGI_FORMATS.BC7_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC7_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_BPTC_UNORM_EXT;
                        blockSize         = 16;
                        break;

                    case DX10Header.DXGI_FORMATS.BC7_UNORM_SRGB:
                        CompressionFormat = CompressionFormats.SRGB_ALPHA_BPTC_UNORM_EXT;
                        blockSize         = 16;
                        break;

                    // TODO: Add support for BC1 SRGB, BC2, BC3 SRGB, BC4, and BC6
                    default:
                        throw new NotImplementedException(string.Format(
                                                              "Reading DX10 DXGI type \"{0}\" is not yet supported.",
                                                              dx10Header.DXGIFormat));
                    }

                    break;
                }

                // DXT1
                case DDSPixelFormat.FOURCCS.DXT1:
                    CompressionFormat = CompressionFormats.RGB_S3TC_DXT1_EXT;
                    blockSize         = 8;
                    break;

                // DXT3
                case DDSPixelFormat.FOURCCS.DXT3:
                    CompressionFormat = CompressionFormats.RGBA_S3TC_DXT3_EXT;
                    blockSize         = 16;
                    break;

                // DXT5
                case DDSPixelFormat.FOURCCS.DXT5:
                case DDSPixelFormat.FOURCCS.ATI2:
                case DDSPixelFormat.FOURCCS.BC5S:
                    CompressionFormat = CompressionFormats.RGBA_S3TC_DXT5_EXT;
                    blockSize         = 16;
                    break;

                // TODO: Add support for DXT2 and DXT4
                default:
                    throw new NotImplementedException(string.Format("{0} \"{1}\" {2}",
                                                                    "Reading DDS files with FOURCC",
                                                                    Header.PixelFormat.FourCC,
                                                                    "is not yet supported."));
                }
            }
            else
            {
                if (!Header.PixelFormat.HasFlag(DDSPixelFormat.FLAGS.RGB))
                {
                    throw new NotImplementedException(
                              "Reading DDS files without RGB data is not yet supported.");
                }

                if (Header.PixelFormat.RGBBitCount % 8 != 0)
                {
                    throw new InvalidDataException(
                              "RGBBitCount must be divisible by 8.");
                }

                if (Header.PixelFormat.RGBBitCount > 32)
                {
                    throw new InvalidDataException(
                              "RGBBitCount must be less than or equal to 32.");
                }

                if (Header.PixelFormat.RGBBitCount != 32)
                {
                    throw new NotImplementedException(
                              "Reading DDS files with non 32-bit data is not yet supported.");
                }

                pixelsPerBlock    = 1;
                CompressionFormat = CompressionFormats.None;
                blockSize         = (byte)(Header.PixelFormat.RGBBitCount / 8);
                PixelFormat       = PixelFormats.RGBA;
            }

            // Whether or not uncompressed pixels need to be re-arranged to RGBA
            bool isARGB = (CompressionFormat == CompressionFormats.None &&
                           Header.PixelFormat.RGBBitCount == 32 &&
                           Header.PixelFormat.ABitMask == 0xFF000000 &&
                           Header.PixelFormat.RBitMask == 0xFF0000 &&
                           Header.PixelFormat.GBitMask == 0xFF00 &&
                           Header.PixelFormat.BBitMask == 0xFF);

            // Data
            uint width = Width, height = Height;

            ColorData = new byte[mipmapCount * depth][];

            for (uint slice = 0; slice < depth; ++slice)
            {
                for (uint level = 0; level < mipmapCount; ++level)
                {
                    // Pad out width/height to 4x4 blocks
                    if (CompressionFormat != CompressionFormats.None)
                    {
                        if (width % 4 != 0)
                        {
                            width = ((width / 4) + 1) * 4;
                        }

                        if (height % 4 != 0)
                        {
                            height = ((height / 4) + 1) * 4;
                        }
                    }

                    // Compute size of this block
                    uint size = ((width * height) / pixelsPerBlock) * blockSize;

                    // Re-arrange uncompressed pixels to RGBA8 format if necessary
                    if (isARGB)
                    {
                        uint p;
                        ColorData[level] = new byte[size];

                        for (uint i = 0; i < size; i += 4)
                        {
                            // Convert from ARGB8 to RGBA8
                            p = reader.ReadUInt32();
                            ColorData[level][i]     = (byte)((p & Header.PixelFormat.RBitMask) >> 16);
                            ColorData[level][i + 1] =
                                (byte)((p & Header.PixelFormat.GBitMask) >> 8);

                            ColorData[level][i + 2] = (byte)(p & Header.PixelFormat.BBitMask);
                            ColorData[level][i + 3] =
                                (byte)((p & Header.PixelFormat.ABitMask) >> 24);
                        }
                    }

                    // Otherwise, simply read the block
                    else
                    {
                        ColorData[level] = reader.ReadBytes((int)size);
                    }

                    // Divide width/height by 2 for the next mipmap
                    width  /= 2;
                    height /= 2;
                }
            }
        }