示例#1
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);
        }
示例#2
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);
        }
示例#3
0
        // Methods
        public override void Load(Stream fileStream)
        {
            // HEADER
            var  reader         = new ExtendedBinaryReader(fileStream, Encoding.ASCII, true);
            uint fileCount      = reader.ReadUInt32();
            uint entriesOffset  = reader.ReadUInt32();
            uint fileDataOffset = reader.ReadUInt32();

            // DATA
            var stringBuffer = new char[stringBufferSize];
            var fileEntries  = new FileEntry[fileCount];

            reader.JumpTo(entriesOffset, true);

            for (uint i = 0; i < fileCount; ++i)
            {
                // Read File Name
                reader.Read(stringBuffer, 0, stringBufferSize);
                string fileName =
                    new string(stringBuffer).Replace("\0", string.Empty);

                // Read File Entry Data
                uint fileIndex = reader.ReadUInt32();
                fileEntries[fileIndex] = new FileEntry()
                {
                    FileName         = fileName,
                    FileIndex        = fileIndex,
                    DataOffset       = reader.ReadUInt32(),
                    DataLength       = reader.ReadUInt32(),
                    UncompressedSize = reader.ReadUInt32()
                };
            }

            // Read File Data
            for (uint i = 0; i < fileCount; ++i)
            {
                var fileEntry = fileEntries[i];
                var data      = new byte[fileEntry.DataLength];
                int pos       = 0;

                reader.JumpTo(fileEntry.DataOffset, true);
                while (pos < data.Length)
                {
                    // TODO: De-compress files.
                    pos += reader.Read(data, pos, data.Length - pos);
                }

                // Add File to Files List
                Data.Add(new ArchiveFile(fileEntry.FileName, data));
            }
        }
        /// <summary>
        /// Gets the StreamBlock from instruction and jumps to it
        /// </summary>
        /// <param name="index">Database Param Index</param>
        /// <param name="reader">The reader used to jump to the block</param>
        /// <returns>a StreamBlock containing the range of data to access</returns>
        public StreamBlock GetStreamBlockAndJump(int index, ExtendedBinaryReader reader)
        {
            var streamBlock = Instructions[index].GetArgument <StreamBlock>(1);

            reader.JumpTo(streamBlock);
            return(streamBlock);
        }
        // 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);
                }
            }
        }
示例#6
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;
                }
            }
        }
        // Methods
        public override void Read(ExtendedBinaryReader reader)
        {
            FileSize       = reader.ReadUInt32();
            RootNodeType   = reader.ReadUInt32();
            RootNodeSize   = reader.ReadUInt32();
            RootNodeOffset = reader.ReadUInt32();
            FooterOffset   = reader.ReadUInt32();
            FileEndOffset  = reader.ReadUInt32();

            reader.Offset = RootNodeOffset;
            reader.JumpTo(RootNodeOffset);
        }
示例#8
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);
        }
示例#9
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);
        }
示例#10
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);
        }
        // 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();
        }
示例#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 void Read(ExtendedBinaryReader reader, uint textureCount)
        {
            // Texture Offsets
            var textureOffsets = new uint[textureCount];

            for (uint i = 0; i < textureCount; ++i)
            {
                textureOffsets[i] = reader.ReadUInt32();
            }

            // Textures
            textures.Clear();
            for (uint i = 0; i < textureCount; ++i)
            {
                reader.JumpTo(textureOffsets[i], false);
                textures.Add(new GensTexture(
                                 reader.ReadNullTerminatedString()));
            }
        }
示例#14
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
                });
            }
        }
示例#15
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);
        }
示例#16
0
        public override void Load(Stream fileStream)
        {
            // Header
            var reader  = new ExtendedBinaryReader(fileStream, true);
            var entries = new List <FileEntry>();

            uint sig = reader.ReadUInt32();

            if (sig != Signature)
            {
                throw new InvalidSignatureException(
                          Signature.ToString("X"), sig.ToString("X"));
            }

            uint fileTableOffset = reader.ReadUInt32();
            uint fileTableLength = reader.ReadUInt32();
            uint fileDataOffset  = reader.ReadUInt32();
            uint unknown5        = reader.ReadUInt32();
            uint unknown6        = reader.ReadUInt32();
            uint unknown7        = reader.ReadUInt32();
            uint unknown8        = reader.ReadUInt32();

            // File/Directory Entries
            long fileTableEnd = (fileTableOffset + fileTableLength);

            reader.JumpTo(fileTableOffset);

            while (fileStream.Position < fileTableEnd)
            {
                bool isDirectory = reader.ReadBoolean();
                byte padding1    = reader.ReadByte();

                if (padding1 != 0)
                {
                    fileStream.Position -= 2; // go bacc
                    break;
                }

                var fileEntry = new FileEntry()
                {
                    IsDirectory          = isDirectory,
                    FileNameOffset       = reader.ReadUInt16(),
                    DataOffset           = reader.ReadUInt32(),
                    DataLength           = reader.ReadUInt32(),
                    DataUncompressedSize = reader.ReadUInt32()
                };

                entries.Add(fileEntry);
            }

            // Entry Names
            uint fileNamesOffset = (uint)fileStream.Position;

            foreach (var entry in entries)
            {
                reader.JumpTo(fileNamesOffset + entry.FileNameOffset);
                entry.Name = reader.ReadNullTerminatedString();
            }

            // Entry Data
            ArchiveDirectory dir = null;

            for (int i = 0; i < entries.Count; ++i)
            {
                var entry = entries[i];

                // Directory
                if (entry.IsDirectory)
                {
                    // Generate a HedgeLib directory entry
                    if (i == 0)
                    {
                        continue;
                    }

                    if (entry.DataOffset >= i)
                    {
                        throw new Exception("Entry DataOffset is invalid");
                    }

                    var dirEntry = new ArchiveDirectory(entry.Name);
                    if (entry.DataOffset != 0)
                    {
                        var parentEntry = entries[(int)entry.DataOffset];
                        dirEntry.Parent = parentEntry.Directory;
                    }

                    if (dirEntry.Parent == null)
                    {
                        Data.Add(dirEntry);
                    }
                    else
                    {
                        dirEntry.Parent.Data.Add(dirEntry);
                    }

                    dir = entry.Directory = dirEntry;
                }

                // File
                else
                {
                    if (dir == null)
                    {
                        throw new Exception("Tried to read a file not in a directory!");
                    }

                    var data = new byte[entry.DataUncompressedSize];
                    int offset = 0, size = (int)entry.DataUncompressedSize;
                    reader.JumpTo(entry.DataOffset + 2);

                    using (var gzipStream = new DeflateStream(fileStream,
                                                              CompressionMode.Decompress, true))
                    {
                        while (offset < size)
                        {
                            offset += gzipStream.Read(data,
                                                      offset, (size - offset));
                        }
                    }

                    // Generate a HedgeLib file entry
                    dir.Data.Add(new ArchiveFile(entry.Name, data));
                }
            }
        }
示例#17
0
        public const uint TAGMagic = 0x30474154; // "TAG0" in little-endian

        // Methods
        public static void Read(HavokFile h, ExtendedBinaryReader reader)
        {
            var  fs     = reader.BaseStream;
            long pos    = fs.Position;
            long endPos = pos;

            var types = new List <string>();

            reader.IsBigEndian = true;
            while (pos < fs.Length)
            {
                uint   size    = reader.ReadUInt32();
                string type    = new string(reader.ReadChars(4));
                bool   isParam = (((size & 0xC0000000) >> 24) == 0x40);

                // Remove the param marker from the beginning of the size
                if (isParam)
                {
                    size &= 0xFFFFFF;
                }

                size  -= 8;
                pos    = fs.Position;
                endPos = pos + size;

                Console.WriteLine("{0}: \"{1}\"",
                                  (isParam) ? "Parameter" : "Section",
                                  type);

                // Read based on type
                switch (type)
                {
                // SDK Version
                case "SDKV":
                    h.ContentsVersion = new string(reader.ReadChars((int)size));
                    Console.WriteLine($"Contents Version: {h.ContentsVersion}");
                    break;

                case "DATA":
                    ReadDATASection();
                    break;

                // Type Strings
                case "TSTR":
                {
                    Console.WriteLine();
                    while (fs.Position < endPos)
                    {
                        string t = reader.ReadNullTerminatedString();
                        if (string.IsNullOrEmpty(t))
                        {
                            continue;
                        }

                        Console.WriteLine(t);
                        types.Add(t);
                        // TODO
                    }
                    Console.WriteLine();
                    break;
                }

                // Type Names (??)
                case "TNAM":
                {
                    uint unknown1 = reader.ReadUInt32();
                    // TODO
                    break;
                }

                // Format Strings
                case "FSTR":
                {
                    Console.WriteLine();
                    while (fs.Position < endPos)
                    {
                        string t = reader.ReadNullTerminatedString();
                        if (string.IsNullOrEmpty(t))
                        {
                            continue;
                        }

                        Console.WriteLine(t);
                        // TODO
                    }
                    Console.WriteLine();
                    // TODO
                    break;
                }
                }

                // TODO

                // Jump ahead to the next parameter
                if (isParam)
                {
                    pos = endPos;

                    if (fs.Position != pos)
                    {
                        reader.JumpTo(pos);
                    }
                }
            }

            // Sub-Methods
            //HavokSection ReadSection()
            //{
            //    var section = new HavokSection();
            //    // TODO
            //    return section;
            //}

            void ReadDATASection()
            {
                reader.IsBigEndian = false; // TODO

                ulong unknown1 = reader.ReadUInt64();
                ulong unknown2 = reader.ReadUInt64();
                ulong unknown3 = reader.ReadUInt64();
                ulong unknown4 = reader.ReadUInt64();
                ulong unknown5 = reader.ReadUInt64();

                for (uint i = 0; i < unknown1; ++i)
                {
                    string s = reader.ReadNullTerminatedString();
                    Console.WriteLine(s);
                }
                // TODO

                // Padding Checks
                if (unknown2 != 0)
                {
                    Console.WriteLine($"WARNING: DATA Unknown2 != 0 ({unknown2})");
                }

                reader.IsBigEndian = true; // TODO
            }
        }
示例#18
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);
        }
        protected void LoadHeroesArchive(ExtendedBinaryReader reader)
        {
            // HEADER
            uint padding = reader.ReadUInt32();

            if (padding != 0)
            {
                Console.WriteLine("WARNING: Padding is not 0! ({0})", padding);
            }

            uint fileSize = reader.ReadUInt32() + 0xC;

            if (fileSize != reader.BaseStream.Length)
            {
                // Written like this to avoid the + operator and keep the line under 100 chars
                Console.WriteLine("{0} (Got {1} expected {2})",
                                  "WARNING: File-Size in archive appears incorrect!",
                                  fileSize, reader.BaseStream.Length);
            }

            Magic = reader.ReadUInt32();
            uint unknown1 = reader.ReadUInt32();

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

            uint dataOffset = reader.ReadUInt32(); // TODO: Ensure this is correct
            uint magic2     = reader.ReadUInt32();

            // DATA
            var stringBuffer = new char[StringLength];
            var fileNames    = new string[FileEntryCount];

            // File Names
            for (uint i = 0; i < FileEntryCount; ++i)
            {
                if (reader.BaseStream.Position + StringLength >= fileSize)
                {
                    break;
                }

                reader.Read(stringBuffer, 0, StringLength);
                fileNames[i] = new string(stringBuffer).Replace("\0", string.Empty);
            }

            // File Entries
            reader.JumpTo(dataOffset, true);

            while (reader.BaseStream.Position < fileSize)
            {
                uint fileNameIndex = reader.ReadUInt32();
                uint dataLength    = reader.ReadUInt32();
                uint magic3        = reader.ReadUInt32();

                if (dataLength > 0)
                {
                    var data = reader.ReadBytes((int)dataLength);
                    Data.Add(new ArchiveFile(fileNames[fileNameIndex], data));
                }
            }
        }
示例#20
0
        private static SetObject ReadObject(ExtendedBinaryReader reader,
                                            SetObjectType objTemplate, string objType, SOBJType type,
                                            bool rawDataMode = false) // true = full, false = only remaining bytes
        {
            // For some reason these separate values are saved as one uint rather than two ushorts.
            // Because of this, the values are in a different order depending on endianness, and
            // this is the easiest known way to read them.
            uint   unknownValue = reader.ReadUInt32();
            ushort unknown1     = (ushort)((unknownValue >> 16) & 0xFFFF);
            ushort objID        = (ushort)(unknownValue & 0xFFFF);

            var obj = new SetObject()
            {
                ObjectType = objType,
                ObjectID   = objID
            };

            uint  unknown2 = reader.ReadUInt32();
            uint  unknown3 = reader.ReadUInt32();
            float unknown4 = reader.ReadSingle();

            float rangeIn          = reader.ReadSingle();
            float rangeOut         = reader.ReadSingle();
            uint  parent           = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0;
            uint  transformsOffset = reader.ReadUInt32();

            uint transformCount = reader.ReadUInt32();
            uint unknown5       = reader.ReadUInt32();
            uint unknown6       = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0;
            uint unknown7       = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0;

            // Call me crazy, but I have a weird feeling these values aren't JUST padding
            if (unknown3 != 0 || unknown5 != 0 || unknown6 != 0 || unknown7 != 0)
            {
                Console.WriteLine("WARNING: Not padding?! ({0},{1},{2},{3})",
                                  unknown3, unknown5, unknown6, unknown7);
            }

            // Add custom data to object
            obj.CustomData.Add("Unknown1", new SetObjectParam(typeof(ushort), unknown1));
            obj.CustomData.Add("Unknown2", new SetObjectParam(typeof(uint), unknown2));
            obj.CustomData.Add("Unknown3", new SetObjectParam(typeof(uint), unknown3));
            obj.CustomData.Add("Unknown4", new SetObjectParam(typeof(float), unknown4));
            obj.CustomData.Add("RangeIn", new SetObjectParam(typeof(float), rangeIn));
            obj.CustomData.Add("RangeOut", new SetObjectParam(typeof(float), rangeOut));

            if (type == SOBJType.LostWorld)
            {
                obj.CustomData.Add("Parent", new SetObjectParam(typeof(uint), parent));
            }

            // Skip loading parameters if template doesn't exist
            if (objTemplate != null)
            {
                // Get Raw Byte Length
                var  rawDataLenExtra = objTemplate.GetExtra("RawByteLength");
                long paramBegin      = reader.BaseStream.Position;
                int  rawLength       = 0;

                if (rawDataLenExtra != null &&
                    !string.IsNullOrEmpty(rawDataLenExtra.Value))
                {
                    int.TryParse(rawDataLenExtra.Value, out rawLength);
                }

                // Read all the data then return to beginning
                if (rawDataMode == true && rawLength != 0)
                {
                    obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]),
                                                                          reader.ReadBytes(rawLength)));
                    reader.JumpTo(paramBegin);
                }

                // Parameters
                foreach (var param in objTemplate.Parameters)
                {
                    // For compatibility with SonicGlvl templates.
                    if (param.Name == "Unknown1" || param.Name == "Unknown2" ||
                        param.Name == "Unknown3" || param.Name == "RangeIn" ||
                        param.Name == "RangeOut" || param.Name == "Parent")
                    {
                        continue;
                    }

                    // Read Special Types/Fix Padding
                    if (param.DataType == typeof(uint[]))
                    {
                        // Data Info
                        reader.FixPadding(4);
                        uint arrOffset  = reader.ReadUInt32();
                        uint arrLength  = reader.ReadUInt32();
                        uint arrUnknown = reader.ReadUInt32();
                        long curPos     = reader.BaseStream.Position;

                        // Data
                        var arr = new uint[arrLength];
                        reader.JumpTo(arrOffset, false);

                        for (uint i = 0; i < arrLength; ++i)
                        {
                            arr[i] = reader.ReadUInt32();
                        }

                        obj.Parameters.Add(new SetObjectParam(param.DataType, arr));
                        reader.BaseStream.Position = curPos;
                        continue;
                    }
                    else if (param.DataType == typeof(string))
                    {
                        // Data Info
                        uint   strOffset  = reader.ReadUInt32();
                        uint   strUnknown = reader.ReadUInt32();
                        string str        = null;

                        // Data
                        if (strOffset != 0)
                        {
                            long curPos = reader.BaseStream.Position;
                            reader.JumpTo(strOffset, false);

                            str = reader.ReadNullTerminatedString();
                            reader.BaseStream.Position = curPos;
                        }

                        obj.Parameters.Add(new SetObjectParam(param.DataType, str));
                        continue;
                    }
                    else if (param.DataType == typeof(float) ||
                             param.DataType == typeof(int) || param.DataType == typeof(uint))
                    {
                        reader.FixPadding(4);
                    }
                    else if (type == SOBJType.LostWorld && param.DataType == typeof(Vector3))
                    {
                        reader.FixPadding(16);
                    }

                    // Read Data
                    var objParam = new SetObjectParam(param.DataType,
                                                      reader.ReadByType(param.DataType));
                    obj.Parameters.Add(objParam);
                }

                if (rawDataMode == false)
                {
                    long knownParamLength = (reader.BaseStream.Position - paramBegin);
                    long remainingBytes   = (rawLength - knownParamLength);

                    obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]),
                                                                          reader.ReadBytes((int)remainingBytes)));
                }
            }

            // Transforms
            uint childCount = transformCount - 1;

            obj.Children = new SetObjectTransform[childCount];
            reader.JumpTo(transformsOffset, false);

            obj.Transform = ReadTransform(reader, type == SOBJType.LostWorld);
            for (uint i = 0; i < childCount; ++i)
            {
                obj.Children[i] = ReadTransform(reader,
                                                type == SOBJType.LostWorld);
            }

            return(obj);
        }
示例#21
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);
        }
示例#22
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);
        }
示例#23
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;
                }
            }
        }
示例#24
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);
        }