示例#1
0
        public static WEP FromStream(EndianBinaryReader reader)
        {
            /*=====================================================================
                WEP HEADER (0x50) 80 bytes long
            =====================================================================*/
            reader.Skip(0x04); // TODO: skip magic 0x04 (4 dec) "H01" check for file type?

            byte numJoints = reader.ReadByte();
            byte numGroups = reader.ReadByte();
            ushort numTriangles = reader.ReadUInt16();
            ushort numQuads = reader.ReadUInt16();
            ushort numPolygons = reader.ReadUInt16();
            uint ptrTexture1 = (uint)(reader.ReadUInt32() + 0x10); // same as ptrTexture... why?

            reader.Skip(0x30); // header padding?

            uint ptrTexture = (uint)(reader.ReadUInt32() + 0x10);
            uint ptrGroups = (uint)(reader.ReadUInt32() + 0x10);
            uint ptrVertices = (uint)(reader.ReadUInt32() + 0x10);
            uint ptrPolygons = (uint)(reader.ReadUInt32() + 0x10);

            /*=====================================================================
                LOCALS
            =====================================================================*/
            int numAllPolygons = numTriangles + numQuads + numPolygons;
            int numOfPalettes = 7; // palettes of 2/3 color count.

            /*=====================================================================
                STREAM READER
            =====================================================================*/
            WEP wep = new WEP();

            wep.joints = VSTools.GetJoints(reader, numJoints);
            wep.groups = VSTools.GetGroups(reader, numGroups);
            wep.vertices = VSTools.GetVertices(reader, wep.groups);
            wep.polygons = VSTools.GetPolygons(reader, numAllPolygons);
            wep.textures = VSTools.GetTextures(reader, numOfPalettes);

            return wep;
        }
        public static List<Joint> GetJoints(EndianBinaryReader reader, int numJoints)
        {
            List<Joint> joints = new List<Joint>();

            for (int i = 0; i < numJoints; i++)
            {
                Joint joint = new Joint();
                joint.boneLength = -reader.ReadInt16();

                reader.Skip(2); // no effect on length, just padding

                joint.parentID = reader.ReadSByte();
                joint.x = reader.ReadSByte();
                joint.y = reader.ReadSByte();
                joint.z = reader.ReadSByte();
                joint.mode = reader.ReadSByte(); // does this matter?

                reader.Skip(0x01); // unknown
                reader.Skip(0x06); // always 0? padding?

                joints.Add(joint);
            }
            return joints;
        }
        public void Load(EndianBinaryReader stream)
        {
            if (stream == null || stream.BaseStream.Length == 0)
                throw new ArgumentException("Null or empty stream specified", "stream");

            // Read the header
            byte entryCount = stream.ReadByte();
            stream.Skip(3); // Unknown Constants (0x5E, 0, 0x61)

            // Offset to the first entry (realistically it's right after the header and always 0x8
            int offsetToFirstEntry = stream.ReadInt32();

            // Load categories and their entries.
            stream.BaseStream.Position = offsetToFirstEntry;
            for(int i = 0; i < entryCount; i++)
            {
                Category category = new Category();
                category.Load(stream);

                Categories.Add(category);
            }
        }
示例#4
0
        public VirtualFilesystemDirectory ReadFile(EndianBinaryReader reader)
        {
            if (reader.ReadUInt32() != 0x52415243) // "RARC"
                throw new InvalidDataException("Invalid Magic, not a RARC File");

            uint fileSize = reader.ReadUInt32();
            reader.SkipUInt32(); // Unknown
            uint dataOffset = reader.ReadUInt32() + 0x20;
            reader.Skip(16); // Unknown - 4 unsigned ints
            uint numNodes = reader.ReadUInt32();
            reader.Skip(8); // Unknown - 2 unsigned ints
            uint fileEntryOffset = reader.ReadUInt32() + 0x20;
            reader.SkipUInt32(); // Unknown
            uint stringTableOffset = reader.ReadUInt32() + 0x20;
            reader.Skip(8); // Unknown - 2 unsigned ints.

            // Read all of the node headers.
            Node[] nodes = new Node[numNodes];

            for (int i = 0; i < numNodes; i++)
            {
                nodes[i] = new Node
                {
                    Type = new string(reader.ReadChars(4)),
                    Name = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt32()),
                    NameHashcode = reader.ReadUInt16(),
                    Entries = new FileEntry[reader.ReadUInt16()],
                    FirstFileOffset = reader.ReadUInt32()
                };
            }

            // Create a virtual directory for every folder within the ARC before we process any of them.
            List<VirtualFilesystemDirectory> allDirs = new List<VirtualFilesystemDirectory>(nodes.Length);
            foreach (Node node in nodes)
            {
                VirtualFilesystemDirectory vfDir = new VirtualFilesystemDirectory(node.Name);
                allDirs.Add(vfDir);
            }

            for (int k = 0; k < nodes.Length; k++)
            {
                Node node = nodes[k];
                VirtualFilesystemDirectory curDir = allDirs[k];

                for (int i = 0; i < node.Entries.Length; i++)
                {
                    // Jump to the entry's offset in the file.
                    reader.BaseStream.Position = fileEntryOffset + ((node.FirstFileOffset + i) * 0x14); // 0x14 is the size of a File Entry in bytes
                    node.Entries[i] = new FileEntry();
                    node.Entries[i].ID = reader.ReadUInt16();
                    node.Entries[i].NameHashcode = reader.ReadUInt16();
                    node.Entries[i].Type = reader.ReadByte();
                    reader.SkipByte(); // Padding
                    node.Entries[i].Name = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt16());

                    // Skip these ones cause I don't know how computers work.
                    if (node.Entries[i].Name == "." || node.Entries[i].Name == "..")
                        continue;

                    uint entryDataOffset = reader.ReadUInt32();
                    uint dataSize = reader.ReadUInt32();

                    // If it's a directory, then entryDataOffset contains the index of the parent node
                    if (node.Entries[i].IsDirectory)
                    {
                        node.Entries[i].SubDirIndex = entryDataOffset;
                        var newSubDir = allDirs[(int)entryDataOffset];
                        curDir.Children.Add(newSubDir);
                    }
                    else
                    {
                        node.Entries[i].Data = reader.ReadBytesAt(dataOffset + entryDataOffset, (int)dataSize);

                        string fileName = Path.GetFileNameWithoutExtension(node.Entries[i].Name);
                        string extension = Path.GetExtension(node.Entries[i].Name);

                        var vfFileContents = new VirtualFileContents(node.Entries[i].Data);
                        VirtualFilesystemFile vfFile = new VirtualFilesystemFile(fileName, extension, vfFileContents);
                        curDir.Children.Add(vfFile);
                    }

                    reader.SkipInt32(); // Padding
                }
            }

            // The ROOT directory should always be the first node. We don't have access to the node's TYPE anymore
            // so we're going to assume its always the first one listed.
            return allDirs.Count > 0 ? allDirs[0] : null;
        }
        public static List<Vertex> GetVertices(EndianBinaryReader reader, List<Group> groups)
        {
            List<Vertex> vertices = new List<Vertex>();
            for (int i = 0, g = 0; i < groups[groups.Count - 1].lastVertex; i++)
            {
                if (i >= groups[g].lastVertex)
                {
                    g++; // next group
                }

                Vertex vertex = new Vertex();

                vertex.x = reader.ReadInt16();
                vertex.y = reader.ReadInt16();
                vertex.z = reader.ReadInt16();

                reader.Skip(0x02); // padding

                vertex.groupID = g;
                vertex.boneID = groups[g].boneID;

                vertices.Add(vertex);
            }
            return vertices;
        }
        public void Load(EndianBinaryReader reader)
        {
            int numVerts = reader.ReadInt32();

            int vertsOffset = reader.ReadInt32();

            int numFaces = reader.ReadInt32();

            int facesOffset = reader.ReadInt32();

            reader.BaseStream.Position = vertsOffset;

            List<Vector3> vertsList = new List<Vector3>();

            for (int i = 0; i < numVerts; i++)
            {
                vertsList.Add(new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()));
            }

            Vertexes = vertsList.ToArray();

            reader.BaseStream.Position = facesOffset;

            List<int> facesList = new List<int>();

            for (int i = 0; i < numFaces; i++)
            {
                facesList.Add(reader.ReadInt16());

                facesList.Add(reader.ReadInt16());

                facesList.Add(reader.ReadInt16());

                reader.Skip(4);
            }

            Meshes = facesList.ToArray();

            //Generate a buffer on the GPU and get the ID to it
            GL.GenBuffers(1, out _glVbo);

            //This "binds" the buffer. Once a buffer is bound, all actions are relative to it until another buffer is bound.
            GL.BindBuffer(BufferTarget.ArrayBuffer, _glVbo);

            //This uploads data to the currently bound buffer from the CPU -> GPU. This only needs to be done with the data changes (ie: you edited a vertexes position on the cpu side)
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertexes.Length * Vector3.SizeInBytes), Vertexes,
                BufferUsageHint.StaticDraw);

            //Now we're going to repeat the same process for the Element buffer, which is what OpenGL calls indicies. (Notice how it's basically identical?)
            GL.GenBuffers(1, out _glEbo);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _glEbo);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(Meshes.Length * 4), Meshes,
                BufferUsageHint.StaticDraw);
        }
示例#7
0
        public static SHP FromStream(EndianBinaryReader reader)
        {
            /*=====================================================================
                WEP HEADER (0x50) 80 bytes long
            =====================================================================*/
            reader.Skip(0x04); // TODO: skip magic 0x04 (4 dec) "H01" check for file type?

            byte numJoints = reader.ReadByte();
            byte numGroups = reader.ReadByte();
            ushort numTriangles = reader.ReadUInt16();
            ushort numQuads = reader.ReadUInt16();
            ushort numPolygons = reader.ReadUInt16();

            // Overlay cords and size
            // First is Eyes, Second is Mouth, 3-8 are? special frames?
            byte[] overlayX = new byte[8];
            byte[] overlayY = new byte[8];
            byte[] width = new byte[8];
            byte[] height = new byte[8];

            for (int i = 0; i < 8; i++)
            {
                overlayX[i] = reader.ReadByte();
                overlayY[i] = reader.ReadByte();
                width[i] = reader.ReadByte();
                height[i] = reader.ReadByte();
            }

            reader.Skip(0x24); // unkown, skip padding assumed

            reader.Skip(0x06); // skip collision size and height (shape is a cylinder)
            reader.Skip(0x02); // skip menu position Y
            reader.Skip(0x0C); // skip Unknown
            reader.Skip(0x02); // skip Shadow radius
            reader.Skip(0x02); // skip Shadow size increase rate
            reader.Skip(0x02); // skip Shadow size decrease rate
            reader.Skip(0x04); // skip Unknown
            reader.Skip(0x02); // skip Menu scale
            reader.Skip(0x02); // skip Unknown
            reader.Skip(0x02); // skip Target sphere position Y
            reader.Skip(0x08); // skip Unknown

            uint[] animLBA = new uint[12];
            for (int i = 0; i < 12; i++)
            {
                animLBA[i] = reader.ReadUInt32();
            }

            ushort[] chainIDs = new ushort[13];
            for (int i = 0; i < 12; i++)
            {
                chainIDs[i] = reader.ReadUInt16();
            }

            uint[] specialLBAs = new uint[4];
            for (int i = 0; i < 4; i++)
            {
                specialLBAs[i] = reader.ReadUInt32();
            }

            reader.Skip(0x20); //unknown (probably more LBA tables, there are also special attack ids stored here.)

            uint ptrMagic = (uint)(reader.ReadUInt32() + 0xF8); // same as ptrTexture... why?

            reader.Skip(0x18 * 2); // unknown (noticeable effects when casting spells)

            uint ptrAkao = (uint)(reader.ReadUInt32() + 0xF8);
            uint ptrGroups = (uint)(reader.ReadUInt32() + 0xF8);
            uint ptrVertices = (uint)(reader.ReadUInt32() + 0xF8);
            uint ptrPolygons = (uint)(reader.ReadUInt32() + 0xF8);

            /*=====================================================================
                LOCALS
            =====================================================================*/
            int numAllPolygons = numTriangles + numQuads + numPolygons;
            int numOfPalettes = 2; // Enemies have two palettes that add variation. No use on main characters

            /*=====================================================================
                STREAM READER
            =====================================================================*/
            SHP shp = new SHP();

            shp.joints = VSTools.GetJoints(reader, numJoints);
            shp.groups = VSTools.GetGroups(reader, numGroups);
            shp.vertices = VSTools.GetVertices(reader, shp.groups);
            shp.polygons = VSTools.GetPolygons(reader, numAllPolygons);

            // skip AKAO
            reader.Skip(ptrMagic - ptrAkao);
            // skip magic section
            reader.Skip(4); // unknown
            reader.Skip(reader.ReadUInt32()); // skip length of the magic section.

            shp.textures = VSTools.GetTextures(reader, numOfPalettes);

            return shp;
        }