Ejemplo n.º 1
0
        public MsaAnimation(Subfile basis)
        {
            dataSectionOffset       = Utility.ReadUInt32BigEndian(basis.filebytes, 0x6C);
            boneTableRelativeOffset = Utility.ReadUInt32BigEndian(basis.filebytes, 0x40);

            firstTableOffset  = Utility.ReadUInt32BigEndian(basis.filebytes, 0x84);
            firstTableCount   = Utility.ReadUInt32BigEndian(basis.filebytes, 0x88);
            secondTableOffset = Utility.ReadUInt32BigEndian(basis.filebytes, 0x8C);
            secondTableCount  = Utility.ReadUInt32BigEndian(basis.filebytes, 0x90);

            for (int i = 0; i < firstTableCount; i++)
            {
                table1.Add(new Table1Entry(basis.filebytes, (int)(firstTableOffset + (i * 0x0C)), this));
            }

            for (int i = 0; i < secondTableCount; i++)
            {
                table2.Add(new Table2Entry(basis.filebytes, (int)(secondTableOffset + (i * 0x0C))));
            }

            uint boneTableCount = Utility.ReadUInt32BigEndian(basis.filebytes, (int)(dataSectionOffset + boneTableRelativeOffset + 0x80));

            for (int i = 0; i < boneTableCount; i++)
            {
                boneTable.Add(new BoneTableEntry(basis.filebytes, (int)(dataSectionOffset + boneTableRelativeOffset + 0xF0 + (i * 0x20))));
            }
        }
Ejemplo n.º 2
0
 public hkBoxShape(Subfile basis, int objectOffset)
 {
     x   = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, objectOffset + 0x10));
     y   = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, objectOffset + 0x14));
     z   = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, objectOffset + 0x18));
     unk = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, objectOffset + 0x1C));
 }
Ejemplo n.º 3
0
                public int classOffset;  //offset to the type of object in the class table

                public hkxVirtualFixupEntry(Subfile basis, int pos)
                {
                    objectOffset = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                    pos         += 4;
                    pos         += 4; //skip unk, always 0?
                    classOffset  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                }
Ejemplo n.º 4
0
        public MaterialSet(Subfile basis)
        {
            int number_of_materials = Utility.ReadInt32BigEndian(basis.filebytes, 0x0C);

            List <ulong> hashes = new List <ulong>();

            for (int i = 0; i < number_of_materials; i++)
            {
                hashes.Add(Utility.ReadUInt64BigEndian(basis.filebytes, 0x18 + (i * 8)));
            }

            foreach (Subfile s in global.activePackage.subfiles)
            {
                if (!(s.typeID == (uint)global.TypeID.MATD_MSK || s.typeID == (uint)global.TypeID.MATD_MSA))
                {
                    continue;
                }
                if (hashes.Contains(s.hash))
                {
                    if (s.filebytes == null || s.filebytes.Length == 0)
                    {
                        s.Load();
                    }

                    mats.Add(s.matd);
                }
            }
        }
Ejemplo n.º 5
0
        public static List <hkSimpleMeshShapeTriangle> ParseHkTriangleArray(Subfile basis, int offset)
        {
            int length           = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 4));
            int capacityAndFlags = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 8));

            if (length == 0)
            {
                return(null);
            }

            Console.WriteLine("Going to look for offset " + offset + " in the local fixup table");

            offset = basis.hkx.getLocalFixUpOffset(offset - basis.hkx.dataSection.sectionOffset) + basis.hkx.dataSection.sectionOffset; //go to the offset of the actual array, using the local fixup table

            //now begins the unique bit

            List <hkSimpleMeshShapeTriangle> output = new List <hkSimpleMeshShapeTriangle>();

            for (int i = 0; i < length; i++)
            {
                hkSimpleMeshShapeTriangle t = new hkSimpleMeshShapeTriangle();

                t.v1 = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset));
                t.v2 = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 4));
                t.v3 = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 8));

                output.Add(t);
                //Console.WriteLine("triangle: " + t.v1 + "," + t.v2 + "," + t.v3);
                offset += 12;
            }

            return(output);
        }
Ejemplo n.º 6
0
        public static List <int> ParseHkIntArray(Subfile basis, int offset)
        {
            int length           = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 4));
            int capacityAndFlags = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 8));

            if (length == 0)
            {
                return(null);
            }

            Console.WriteLine("Going to look for offset " + offset + " in the local fixup table");

            offset = basis.hkx.getLocalFixUpOffset(offset - basis.hkx.dataSection.sectionOffset) + basis.hkx.dataSection.sectionOffset; //go to the offset of the actual array, using the local fixup table

            //now begins the unique bit

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

            for (int i = 0; i < length; i++)
            {
                output.Add(Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset)));
                Console.WriteLine("int: " + output[output.Count - 1]);
                offset += 4;
            }

            return(output);
        }
Ejemplo n.º 7
0
        public static List <Vertex> ParseHkVertexArray(Subfile basis, int offset)
        {
            int length           = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 4));
            int capacityAndFlags = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, offset + 8));

            if (length == 0)
            {
                return(null);
            }

            Console.WriteLine("Going to look for offset " + offset + " in the local fixup table");

            offset = basis.hkx.getLocalFixUpOffset(offset - basis.hkx.dataSection.sectionOffset) + basis.hkx.dataSection.sectionOffset; //go to the offset of the actual array, using the local fixup table

            //now begins the unique bit

            List <Vertex> output = new List <Vertex>();

            for (int i = 0; i < length; i++)
            {
                Vertex v = new Vertex();

                v.position.x = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, offset));
                v.position.y = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, offset + 4));
                v.position.z = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, offset + 8));
                v.W          = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, offset + 12));

                output.Add(v);
                //Console.WriteLine("vertex: "+v.X+","+v.Y+","+v.Z);
                offset += 16;
            }
            return(output);
        }
Ejemplo n.º 8
0
        private void backtrackToModelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Subfile s = treeNodesAndSubfiles[FileTree.SelectedNode];

            s.Load();
            backtrackSubfile(s);
        }
Ejemplo n.º 9
0
        public MaterialData(Subfile basis)
        {
            parameters = new List <Param>();
            filename   = basis.filename;

            int pos = 0x10;

            // a lot of the offsets are measured from 0x10

            //now read the parameters!

            pos += 0x08;

            int lengthOfDataSection = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
            int numberOfParams      = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

            //now the param list begins. Each param has 0x10 bytes describing it, with an offset to later in the file (falling within the data section, but measured from 0x10)

            for (int i = 0; i < numberOfParams; i++)
            {
                parameters.Add(new Param(basis.filebytes, pos));
                pos += 0x10;
            }

            //now process the data for each parameter

            foreach (Param parameter in parameters)
            {
                pos = 0x10 + parameter.dataOffset;

                switch (parameter.paramType)
                {
                case MaterialParameter.diffuseMap:
                    ulong hash_of_diffuse_texture = (ulong)Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;
                    hash_of_diffuse_texture |= ((ulong)Utility.ReadUInt32BigEndian(basis.filebytes, pos)) << 32; pos += 4;
                    if (hash_of_diffuse_texture == 0x58CC31A1AC11E901)
                    {
                        Console.WriteLine("Here it is!!");
                    }

                    uint typeID_of_diffuse_texture = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;

                    parameter.diffuse_texture = global.activePackage.FindFileByHashAndTypeID(hash_of_diffuse_texture, typeID_of_diffuse_texture);
                    break;

                default:
                    Console.WriteLine("Unhandled material parameter: " + parameter.paramType);
                    break;
                }
            }
        }
Ejemplo n.º 10
0
        public LLMF(Subfile basis)
        {
            int pos = 0x28;

            int numLevelModels = Utility.ReadInt32BigEndian(basis.filebytes, pos);

            pos += 4;
            int numObjects = Utility.ReadInt32BigEndian(basis.filebytes, pos);

            pos += 4;

            pos = 0x48;

            for (int i = 0; i < numLevelModels; i++)
            {
                levelModels.Add(new LevelEntry()
                {
                    modelHash = Utility.ReverseEndianULong(BitConverter.ToUInt64(basis.filebytes, pos))
                });
                pos += 8;
            }

            for (int i = 0; i < numObjects; i++)
            {
                ObjectEntry newObject = new ObjectEntry();
                newObject.modelHash = Utility.ReverseEndianULong(BitConverter.ToUInt64(basis.filebytes, pos)); pos += 8;
                newObject.X         = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.Y         = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.Z         = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.xRot      = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.yRot      = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.zRot      = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.xScale    = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.yScale    = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                newObject.zScale    = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;

                newObject.materialCount = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

                for (int j = 0; j < newObject.materialCount; j++)
                {
                    pos += 16;
                }

                objects.Add(newObject);
            }
        }
Ejemplo n.º 11
0
            public hkxDataSection(Subfile basis, int offset)
            {
                int pos = offset;

                while (basis.filebytes[pos] != 0x00)
                {
                    name += (char)basis.filebytes[pos];
                    pos++;
                }

                pos = offset + 0x14;    //skips over 4-byte magic 0x000000FF

                sectionOffset           = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                localFixupTableOffset   = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                globalFixupTableOffset  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                virtualFixupTableOffset = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                val4                    = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                val5                    = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;
                val6                    = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                    += 4;

                //now actually read the sections

                pos = sectionOffset + localFixupTableOffset;

                while (pos + 0x08 <= sectionOffset + globalFixupTableOffset)
                {
                    localFixupTable.Add(new hkxLocalFixupEntry(basis, pos));
                    pos += 0x08;
                }

                pos = sectionOffset + virtualFixupTableOffset;

                while (pos + 0x0C <= sectionOffset + val4)
                {
                    virtualFixupTable.Add(new hkxVirtualFixupEntry(basis, pos));
                    pos += 0x0C;
                }
            }
Ejemplo n.º 12
0
        public void ParseHavokObject(Subfile basis, hkxDataSection.hkxVirtualFixupEntry entry)
        {
            for (int i = 0; i < classTable.entries.Count; i++)
            {
                if (classTable.entries[i].offset == entry.classOffset)
                {
                    hkxClassTable.hkxClassTableEntry target = classTable.entries[i];

                    switch (target.name)
                    {
                    case "hkBoxShape":
                        hkBoxShape newBoxShape = new hkBoxShape(basis, dataSection.sectionOffset + entry.objectOffset);
                        havokObjects.Add(newBoxShape);
                        break;

                    case "hkSimpleMeshShape":
                        hkSimpleMeshShape newSimpleMeshShape = new hkSimpleMeshShape(basis, dataSection.sectionOffset + entry.objectOffset);
                        havokObjects.Add(newSimpleMeshShape);

                        obj.Add("o object" + entry.objectOffset);

                        Console.WriteLine("vert count: " + newSimpleMeshShape.vertices.Count);

                        foreach (Vertex v in newSimpleMeshShape.vertices)
                        {
                            obj.Add("v " + v.position.x + " " + v.position.y + " " + v.position.z);
                        }

                        foreach (hkSimpleMeshShapeTriangle f in newSimpleMeshShape.triangles)
                        {
                            obj.Add("f " + (f.v1 + 1 + cumulativeVertCount) + " " + (f.v2 + 1 + cumulativeVertCount) + " " + (f.v3 + 1 + cumulativeVertCount));
                        }

                        cumulativeVertCount += newSimpleMeshShape.vertices.Count;

                        break;

                    default:
                        Console.WriteLine("Unhandled havok object type: " + target.name);
                        break;
                    }
                    break;
                }
            }
        }
Ejemplo n.º 13
0
        private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            Subfile s = treeNodesAndSubfiles[FileTree.SelectedNode];

            s.Load();

            openFileDialog1.Title           = "Replace " + s.filename;
            openFileDialog1.Filter          = "All files (*.*)|*.*";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.CheckPathExists = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                s.filebytes = File.ReadAllBytes(openFileDialog1.FileName);
            }
        }
Ejemplo n.º 14
0
                public hkxClassTableEntry(hkxClassTable parent, Subfile basis, int pos)
                {
                    ID   = BitConverter.ToUInt32(basis.filebytes, pos);
                    pos += 4;
                    unk  = basis.filebytes[pos];
                    pos++;
                    offset = pos - parent.sectionOffset;

                    while (basis.filebytes[pos] != 0x00)
                    {
                        name += (char)basis.filebytes[pos];
                        pos++;
                    }

                    pos++;

                    endOffset = pos;
                }
Ejemplo n.º 15
0
            public hkxClassTable(Subfile basis, int offset)
            {
                int pos = offset;

                while (basis.filebytes[pos] != 0x00)
                {
                    name += (char)basis.filebytes[pos];
                    pos++;
                }

                pos = offset + 0x14;    //skips over 4-byte magic 0x000000FF

                sectionOffset         = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                endOfClassTableOffset = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                val2                  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                val3                  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                val4                  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                val5                  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;
                val6                  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
                pos                  += 4;

                //now actually read the entries

                pos = sectionOffset;

                while (pos < endOfClassTableOffset)
                {
                    hkxClassTableEntry newEntry = new hkxClassTableEntry(this, basis, pos);

                    if (newEntry.ID != 0xFFFFFFFF)
                    {
                        entries.Add(newEntry);
                    }
                    pos = newEntry.endOffset;
                    Console.WriteLine("Added hkx class entry: " + newEntry.name);
                }
                Console.WriteLine(entries.Count);
            }
Ejemplo n.º 16
0
        public hkSimpleMeshShape(Subfile basis, int objectOffset)
        {
            Console.WriteLine("Exporting a hkSimpleMeshShape");

            if (basis.filebytes[objectOffset + 16] == 0)
            {
                disableWelding = false;
            }
            else
            {
                disableWelding = true;
            }

            vertices        = havokUtility.ParseHkVertexArray(basis, objectOffset + 20);
            triangles       = havokUtility.ParseHkTriangleArray(basis, objectOffset + 32);
            materialIndices = havokUtility.ParseHkIntArray(basis, objectOffset + 44);

            radius = Utility.ReverseEndianSingle(BitConverter.ToSingle(basis.filebytes, objectOffset + 56));
        }
Ejemplo n.º 17
0
        public hkxFile(Subfile basis)
        {
            basis.hkx = this;
            obj = new List <string>();
            cumulativeVertCount = 0;

            byte[] withoutHeader = new byte[basis.filebytes.Length - 0x20];
            Array.Copy(basis.filebytes, 0x20, withoutHeader, 0x00, basis.filebytes.Length - 0x20);
            basis.filebytes = withoutHeader;

            classTable  = new hkxClassTable(basis, 0x40);
            dataSection = new hkxDataSection(basis, 0x70);

            foreach (hkxDataSection.hkxVirtualFixupEntry virtualFixupEntry in dataSection.virtualFixupTable)
            {
                ParseHavokObject(basis, virtualFixupEntry);
            }

            System.IO.File.WriteAllLines(basis.filename + ".obj", obj.ToArray());
        }
Ejemplo n.º 18
0
        private void convertModelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog2 = new OpenFileDialog();

            openFileDialog2.Title           = "Select mdl file";
            openFileDialog2.DefaultExt      = "mdl";
            openFileDialog2.Filter          = "MySims 3d models (*.mdl, *.rmdl)|*.mdl;*.rmdl";
            openFileDialog2.CheckFileExists = true;
            openFileDialog2.CheckPathExists = true;
            openFileDialog2.Multiselect     = true;

            if (openFileDialog2.ShowDialog() == DialogResult.OK)
            {
                foreach (string filename in openFileDialog2.FileNames)
                {
                    if (Path.GetExtension(filename) == ".mdl")
                    {
                        ConvertSkyHeroesModel(filename, File.ReadAllBytes(filename));
                    }
                    else
                    {
                        Subfile s = new Subfile();
                        s.filebytes = File.ReadAllBytes(filename);
                        s.rmdl      = new RevoModel(s);

                        SaveFileDialog saveFileDialog1 = new SaveFileDialog();

                        saveFileDialog1.Title           = "Save model";
                        saveFileDialog1.FileName        = "";
                        saveFileDialog1.CheckPathExists = true;
                        saveFileDialog1.Filter          = "Wavefront OBJ (*.obj)|*.obj";

                        if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                        {
                            s.rmdl.GenerateObj(saveFileDialog1.FileName);
                        }
                    }
                }
            }
        }
Ejemplo n.º 19
0
        private void exportAllContextMenuStripButton_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();

            saveFileDialog1.Title           = "Select destination folder";
            saveFileDialog1.FileName        = "Save here";
            saveFileDialog1.CheckPathExists = false;
            saveFileDialog1.CheckFileExists = false;
            saveFileDialog1.Filter          = "Directory |directory";

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                foreach (TreeNode node in FileTree.Nodes[0].Nodes)
                {
                    bool    was_loaded_already = false;
                    Subfile target             = treeNodesAndSubfiles[node];

                    if (target.filebytes == null || target.filebytes.Length == 0)
                    {
                        target.Load();
                    }
                    else
                    {
                        was_loaded_already = true;
                    }

                    target.ExportFile(true, Path.Combine(Path.GetDirectoryName(saveFileDialog1.FileName), target.filename));

                    if (!was_loaded_already)
                    {
                        target.Unload();
                    }
                }
            }

            MessageBox.Show("Export complete.");
        }
Ejemplo n.º 20
0
        public void LoadPackage()
        {
            int currenttypeindexbeingprocessed  = 0;
            int instancesprocessedofcurrenttype = 0;

            using (BinaryReader reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)))
            {
                uint magic = 0;

                magic = Utility.ReverseEndian(reader.ReadUInt32());

                switch (magic)
                {
                case 0x44425046:        //DBPF
                    packageType = PackageType.Kingdom;
                    break;

                case 0x46504244:        //FPBD
                    packageType = PackageType.Agents;
                    break;

                case 0x030502ED:        //Skyheroes
                case 0x03051771:        //Skyheroes
                    packageType = PackageType.SkyHeroes;
                    reader.Close();
                    LoadSkyHeroesPackage();
                    return;

                default:
                    MessageBox.Show("This is not a valid package!", "Package not supported", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    Console.WriteLine("invalid file magic");
                    break;
                }


                if (packageType == PackageType.Agents)
                {
                    majorversion      = Utility.ReverseEndian(reader.ReadUInt32());
                    minorversion      = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown1          = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown2          = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown3          = Utility.ReverseEndian(reader.ReadUInt32());
                    date              = DateTime.FromBinary(Utility.ReverseEndianLong(reader.ReadInt64()));
                    indexmajorversion = Utility.ReverseEndian(reader.ReadUInt32());

                    filecount             = Utility.ReverseEndian(reader.ReadUInt32());
                    indexoffsetdeprecated = Utility.ReverseEndian(reader.ReadUInt32());
                    indexsize             = Utility.ReverseEndian(reader.ReadUInt32());
                    holeentrycount        = Utility.ReverseEndian(reader.ReadUInt32());
                    holeoffset            = Utility.ReverseEndian(reader.ReadUInt32());
                    holesize          = Utility.ReverseEndian(reader.ReadUInt32());
                    indexminorversion = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown4          = Utility.ReverseEndian(reader.ReadUInt32());
                    indexoffset       = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown5          = Utility.ReverseEndian(reader.ReadUInt32());
                    unknown6          = Utility.ReverseEndian(reader.ReadUInt32());
                    reserved1         = Utility.ReverseEndian(reader.ReadUInt32());
                    reserved2         = Utility.ReverseEndian(reader.ReadUInt32());
                }
                else
                {
                    majorversion      = reader.ReadUInt32();
                    minorversion      = reader.ReadUInt32();
                    unknown1          = reader.ReadUInt32();
                    unknown2          = reader.ReadUInt32();
                    unknown3          = reader.ReadUInt32();
                    date              = DateTime.FromBinary(Utility.ReverseEndianLong(reader.ReadInt64()));
                    indexmajorversion = reader.ReadUInt32();

                    filecount             = reader.ReadUInt32();
                    indexoffsetdeprecated = reader.ReadUInt32();
                    indexsize             = reader.ReadUInt32();
                    holeentrycount        = reader.ReadUInt32();
                    holeoffset            = reader.ReadUInt32();
                    holesize          = reader.ReadUInt32();
                    indexminorversion = reader.ReadUInt32();
                    indexoffset       = reader.ReadUInt32();
                    unknown5          = reader.ReadUInt32();
                    unknown6          = reader.ReadUInt32();
                    reserved1         = reader.ReadUInt32();
                    reserved2         = reader.ReadUInt32();
                }

                Console.WriteLine("Package date: " + date.ToString());


                reader.BaseStream.Position = indexoffset;

                //index header

                if (packageType == PackageType.Agents)
                {
                    indexnumberofentries = Utility.ReverseEndianULong(reader.ReadUInt64());

                    for (uint i = 0; i < indexnumberofentries; i++)  //a bunch of entries that describe how many files there are of each type
                    {
                        IndexEntry newEntry = new IndexEntry();

                        newEntry.typeID  = Utility.ReverseEndian(reader.ReadUInt32());
                        newEntry.groupID = Utility.ReverseEndian(reader.ReadUInt32());
                        newEntry.typeNumberOfInstances = Utility.ReverseEndian(reader.ReadUInt32());
                        newEntry.indexnulls            = Utility.ReverseEndian(reader.ReadUInt32());

                        IndexEntries.Add(newEntry);
                    }

                    currenttypeindexbeingprocessed  = 0;
                    instancesprocessedofcurrenttype = 0;

                    for (uint i = 0; i < filecount; i++)     //go through the files, they are organised by type, one type after the other. (So X number of type A, as described above, then Y number of type B...)
                    {
                        Subfile newSubfile = new Subfile();
                        newSubfile.hash       = Utility.ReverseEndianULong(reader.ReadUInt64());
                        newSubfile.fileoffset = Utility.ReverseEndian(reader.ReadUInt32());
                        newSubfile.filesize   = Utility.ReverseEndian(reader.ReadUInt32());
                        newSubfile.typeID     = IndexEntries[currenttypeindexbeingprocessed].typeID;
                        newSubfile.groupID    = IndexEntries[currenttypeindexbeingprocessed].groupID;

                        if (IndexEntries[currenttypeindexbeingprocessed].groupID != 0)   //it's compressed
                        {
                            newSubfile.should_be_compressed_when_in_package = true;
                            newSubfile.uncompressedsize = Utility.ReverseEndian(reader.ReadUInt32());
                            Console.WriteLine("Found a compressed file");
                        }

                        instancesprocessedofcurrenttype++;

                        if (instancesprocessedofcurrenttype == IndexEntries[currenttypeindexbeingprocessed].typeNumberOfInstances)
                        {
                            Console.WriteLine("Processed " + instancesprocessedofcurrenttype + " instances of " + currenttypeindexbeingprocessed);
                            currenttypeindexbeingprocessed++;
                            instancesprocessedofcurrenttype = 0;
                        }

                        subfiles.Add(newSubfile);
                    }
                }
                else     //MySims and MySims Kingdom use these
                {
                    MSKindexversion = reader.ReadUInt32();

                    if (MSKindexversion == 0)
                    {
                        Console.WriteLine("index version 0");
                        for (uint i = 0; i < filecount; i++)
                        {
                            Subfile newSubfile = new Subfile();

                            newSubfile.typeID  = reader.ReadUInt32();
                            newSubfile.groupID = reader.ReadUInt32();
                            newSubfile.hash    = (ulong)(reader.ReadUInt32()) << 32;
                            newSubfile.hash   |= (ulong)(reader.ReadUInt32());

                            newSubfile.fileoffset       = reader.ReadUInt32();
                            newSubfile.filesize         = reader.ReadUInt32() & 0x7FFFFFFF;
                            newSubfile.uncompressedsize = reader.ReadUInt32();
                            reader.BaseStream.Position += 0x04; //flags

                            if (newSubfile.filesize == newSubfile.uncompressedsize)
                            {
                                newSubfile.uncompressedsize = 0;
                            }
                            else
                            {
                                newSubfile.should_be_compressed_when_in_package = true;
                            }

                            subfiles.Add(newSubfile);
                        }
                    }
                    else if (MSKindexversion == 1)
                    {
                        MessageBox.Show("Index version 1 not implemented!");
                    }
                    else if (MSKindexversion == 2)
                    {
                        Console.WriteLine("index version 2");

                        reader.BaseStream.Position += 4;

                        for (uint i = 0; i < filecount; i++)
                        {
                            Subfile newSubfile = new Subfile();

                            newSubfile.typeID = reader.ReadUInt32();
                            newSubfile.hash   = (ulong)(reader.ReadUInt32()) << 32;
                            newSubfile.hash  |= (ulong)(reader.ReadUInt32());

                            newSubfile.fileoffset       = reader.ReadUInt32();
                            newSubfile.filesize         = reader.ReadUInt32() & 0x7FFFFFFF;
                            newSubfile.uncompressedsize = reader.ReadUInt32();
                            reader.BaseStream.Position += 0x04; //flags

                            if (newSubfile.filesize == newSubfile.uncompressedsize)
                            {
                                newSubfile.uncompressedsize = 0;
                            }
                            else
                            {
                                newSubfile.should_be_compressed_when_in_package = true;
                            }

                            subfiles.Add(newSubfile);
                        }
                    }
                    else if (MSKindexversion == 3)
                    {
                        Console.WriteLine("index version 3");
                        uint allFilesTypeID = reader.ReadUInt32();
                        reader.BaseStream.Position += 4;

                        for (uint i = 0; i < filecount; i++)
                        {
                            Subfile newSubfile = new Subfile();

                            newSubfile.typeID = allFilesTypeID;
                            newSubfile.hash   = (ulong)(reader.ReadUInt32()) << 32;
                            newSubfile.hash  |= (ulong)(reader.ReadUInt32());

                            newSubfile.fileoffset       = reader.ReadUInt32();
                            newSubfile.filesize         = reader.ReadUInt32() & 0x7FFFFFFF;
                            newSubfile.uncompressedsize = reader.ReadUInt32();
                            reader.BaseStream.Position += 0x04; //flags

                            if (newSubfile.filesize == newSubfile.uncompressedsize)
                            {
                                newSubfile.uncompressedsize = 0;
                            }
                            else
                            {
                                newSubfile.should_be_compressed_when_in_package = true;
                            }

                            subfiles.Add(newSubfile);
                        }
                    }
                    else if (MSKindexversion == 4)
                    {
                        Console.WriteLine("index version 4");
                        reader.BaseStream.Position += 4;

                        for (uint i = 0; i < filecount; i++)
                        {
                            Subfile newSubfile = new Subfile();

                            newSubfile.typeID = reader.ReadUInt32();
                            newSubfile.hash   = (ulong)(reader.ReadUInt32()) << 32;
                            newSubfile.hash  |= (ulong)(reader.ReadUInt32());

                            newSubfile.fileoffset       = reader.ReadUInt32();
                            newSubfile.filesize         = reader.ReadUInt32();
                            newSubfile.uncompressedsize = reader.ReadUInt32();

                            if (newSubfile.filesize == newSubfile.uncompressedsize)
                            {
                                newSubfile.uncompressedsize = 0;
                            }
                            else
                            {
                                newSubfile.should_be_compressed_when_in_package = true;
                            }

                            subfiles.Add(newSubfile);
                        }
                    }
                    else if (MSKindexversion == 7)
                    {
                        Console.WriteLine("index version 7");
                        for (uint i = 0; i < filecount; i++)
                        {
                            Subfile newSubfile = new Subfile();

                            newSubfile.typeID  = reader.ReadUInt32();
                            newSubfile.groupID = reader.ReadUInt32();
                            newSubfile.hash    = (ulong)(reader.ReadUInt32()) << 32;
                            newSubfile.hash   |= (ulong)(reader.ReadUInt32());

                            newSubfile.fileoffset       = reader.ReadUInt32();
                            newSubfile.filesize         = reader.ReadUInt32() & 0x7FFFFFFF;
                            newSubfile.uncompressedsize = reader.ReadUInt32();
                            reader.BaseStream.Position += 0x04;     //flags

                            if (newSubfile.filesize == newSubfile.uncompressedsize)
                            {
                                newSubfile.uncompressedsize = 0;
                            }
                            else
                            {
                                newSubfile.should_be_compressed_when_in_package = true;
                            }

                            subfiles.Add(newSubfile);
                        }
                    }
                    else
                    {
                        MessageBox.Show("Unknown index version: " + MSKindexversion);
                        return;
                    }
                }


                //extract files

                Console.WriteLine("filecount " + filecount);

                int filesprocessed = 0;


                List <string> luaFilenamesForDict = new List <string>();

                bool containslua = false;

                for (int i = 0; i < filecount; i++)
                {
                    if (subfiles[i].should_be_compressed_when_in_package)
                    {
                        subfiles[i].has_been_decompressed = false;    //set default state of a compressed file to compressed
                    }

                    {
                        string fileextension = null;

                        switch ((global.TypeID)subfiles[i].typeID)
                        {
                        case global.TypeID.RMDL_MSA:            //RMDL MSA
                            fileextension = ".rmdl";            //TYPE ID 29 54 E7 34
                            break;

                        case global.TypeID.RMDL_MSK:            //RMDL MSK
                            fileextension = ".rmdl";            //          "ModelData"
                            break;

                        case global.TypeID.MATD_MSA:            //MATD MSA
                            fileextension = ".matd";            //TYPE ID E6 64 05 42
                            break;

                        case global.TypeID.MATD_MSK:              //MATD MSK            "MaterialData"
                            fileextension = ".matd";
                            break;

                        case global.TypeID.TPL_MSA:             //altered TPL MSA
                            fileextension = ".tpl";             //TYPE ID 92 AA 4D 6A
                            break;

                        case global.TypeID.TPL_MSK:             //altered TPL MSK      "TextureData"
                            fileextension = ".tpl";
                            break;

                        case global.TypeID.MTST_MSK:          //MTST Material Set MSK       "MaterialSetData"
                            fileextension = ".mtst";
                            break;

                        case global.TypeID.MTST_MSA:             //MTST Material Set MSA
                            fileextension = ".mtst";             //TYPE ID 78 7E 84 2A
                            break;

                        case global.TypeID.FPST_MSK:            //FPST   MySims Kingdom footprint set.    "FootprintData"    contains a model footprint (ftpt) which is possibly documented at http://simswiki.info/wiki.php?title=Sims_3:PackedFileTypes
                        case global.TypeID.FPST_MSA:            //FPST   MySims Agents footprint set.                        contains a model footprint (ftpt) which is possibly documented at http://simswiki.info/wiki.php?title=Sims_3:PackedFileTypes
                            fileextension = ".fpst";            //It's like a heatmap of where sims can walk? Or perhaps which surfaces should generate which kind of footprint (but wouldn't that mean that overhangs wouldn't work?)
                            break;

                        case global.TypeID.BNK_MSA:            //BNKb    big endian BNK    MSA                             vgmstream can decode these.           https://github.com/losnoco/vgmstream/blob/master/src/meta/ea_schl.c
                            fileextension = ".bnk";            //TYPE ID 21 99 BB 60
                            break;

                        case global.TypeID.BNK_MSK:            //BNKb    BNK    MSK (idk which endian, not tested)       "AudioData"             vgmstream can decode these.           https://github.com/losnoco/vgmstream/blob/master/src/meta/ea_schl.c
                            fileextension = ".bnk";
                            break;

                        case global.TypeID.BIG_MSK:        //big
                            fileextension = ".big";        //"AptData" (but it is, of course, a familiar EA .BIG archive)
                            break;

                        case global.TypeID.BIG_MSA:            //BIGF
                            fileextension = ".big";
                            break;

                        case global.TypeID.COLLISION_MSA: //00 00 00 02             There's another, separate filetype that also begins with the 2 magic, but that one doesn't appear as frequently, so this one here is probably the collision type ID
                            //TYPE ID 1A 8F EB 14.
                            fileextension = ".collision"; //mesh collision
                            break;                        //there are mentions of 'rwphysics' in MSA's main.dol; could this mean Renderware Physics, which was indeed a product available at the time?

                        case global.TypeID.FX:            //FX
                            fileextension = ".fx";
                            break;

                        case global.TypeID.LUAC_MSA:            //LUAC MSA
                            fileextension = ".luac";
                            containslua   = true;
                            break;

                        case global.TypeID.LUAC_MSK:             //LUAC MSK  "LuaObjectData"
                            fileextension = ".luac";
                            containslua   = true;
                            break;

                        case global.TypeID.SLOT_MSA:         //SLOT MSA
                            fileextension = ".slot";
                            break;

                        case global.TypeID.SLOT_MSK:         //SLOT MSK
                            fileextension = ".slot";         //"SlotData"
                            break;

                        case global.TypeID.PARTICLES_MSA:           //particles file
                            fileextension = ".particles";           //TYPE ID 28 70 78 64
                            break;

                        case global.TypeID.BUILDABLEREGION_MSA:           //00 00 00 03        buildable region MSA
                            fileextension = ".buildableregion";
                            break;

                        case global.TypeID.BUILDABLEREGION_MSK:           //buildable region MSK        "BuildableRegionData"
                            fileextension = ".buildableregion";
                            break;

                        case global.TypeID.LLMF_MSA:                         //LLMF level bin MSA
                            fileextension = ".llmf";
                            break;

                        case global.TypeID.LLMF_MSK:                         //LLMF level bin MSK   "LevelData"
                            fileextension = ".llmf";
                            break;

                        case global.TypeID.RIG_MSA:        //RIG MSA                   //Interesting granny struct info at 0x49CFDD in MSA's main.dol
                            fileextension = ".grannyrig";  //TYPE ID 46 72 E5 BD
                            break;

                        case global.TypeID.RIG_MSK:        //RIG MSK
                            fileextension = ".grannyrig";  // "RigData"
                            break;

                        case global.TypeID.ANIMCLIP_MSA:        //ANIMATION MSA
                            fileextension = ".clip";            //TYPE ID D6 BE DA 43
                            break;

                        case global.TypeID.ANIMCLIP_MSK:        //ANIMATION MSK         "ClipData"
                            fileextension = ".clip";
                            break;

                        case global.TypeID.LTST_MSA:
                            fileextension = ".ltst";        //possibly lighting set?
                            break;

                        case global.TypeID.TTF_MSK:             //TrueType font MySims Kingdom
                        case global.TypeID.TTF_MSA:             //TrueType font MySims Agents
                            fileextension = ".ttf";             //TYPE ID 27 6C A4 B9
                            break;

                        case global.TypeID.HKX_MSK:        //MSK HKX havok collision file
                            fileextension = ".hkx";        // "PhysicsData"
                            break;

                        case global.TypeID.OGVD_MSK:
                            fileextension = ".objectGridVolumeData";       //MSK "ObjectGridVolumeData"
                            break;

                        case global.TypeID.OGVD_MSA:           //00 00 00 02           MSA ObjectGridVolumeData bounding box collision (for very simple objects)
                            fileextension = ".objectGridVolumeData";
                            break;

                        case global.TypeID.SPD_MSK:
                            fileextension = ".snapPointData";       //MSK "SnapPointData"
                            break;

                        case global.TypeID.SPD_MSA:           //00 00 00 03          MSA SnapPointData, most likely
                            fileextension = ".snapPointData";
                            break;

                        case global.TypeID.VGD_MSK:
                            fileextension = ".voxelGridData";       //MSK "VoxelGridData"
                            break;

                        case global.TypeID.VGD_MSA:           //00 00 00 01      MSA VoxelGridData, most likely, most likely
                            fileextension = ".voxelGridData";
                            break;

                        case global.TypeID.MODEL_MS:       //model          used by MySims, not the same as rmdl
                            fileextension = ".model";
                            break;

                        case global.TypeID.KEYNAMEMAP_MS:
                            fileextension = ".KeyNameMap";
                            break;

                        case global.TypeID.GEOMETRY_MS:
                            fileextension = ".geometry";
                            break;

                        case global.TypeID.OLDSPEEDTREE_MS:
                            fileextension = ".oldSpeedTree";
                            break;

                        case global.TypeID.SPEEDTREE_MS:
                            fileextension = ".speedTree";
                            break;

                        case global.TypeID.COMPOSITETEXTURE_MS:
                            fileextension = ".compositeTexture";
                            break;

                        case global.TypeID.SIMOUTFIT_MS:
                            fileextension = ".simOutfit";
                            break;

                        case global.TypeID.LEVELXML_MS:
                            fileextension = ".levelXml";
                            break;

                        case global.TypeID.LUA_MSK:        //uncompiled lua script "LuaTextData"
                            fileextension = ".lua";
                            break;

                        case global.TypeID.LIGHTSETXML_MS:        //Light set XML MySims
                            fileextension = ".lightSetXml";
                            break;

                        case global.TypeID.LIGHTSETBIN_MSK:        //Light set bin MySims
                            fileextension = ".lightSetBin";        //Named "LightSetData" in MSK's executable
                            break;

                        case global.TypeID.XML_MS:       //xml
                            fileextension = ".xml";
                            break;

                        case global.TypeID.FPST_MS:        //footprint set MySims
                            fileextension = ".footprintSet";
                            break;

                        case global.TypeID.OBJECTCONSTRUCTIONXML_MS:        //object construction xml
                            fileextension = ".objectConstructionXml";
                            break;

                        case global.TypeID.OBJECTCONSTRUCTIONBIN_MS:        //object construction bin
                            fileextension = ".objectConstructionBin";
                            break;

                        case global.TypeID.SLOTXML_MS:        //slot xml
                            fileextension = ".slotXml";
                            break;

                        case global.TypeID.SWARM_MSK:        //swm
                            fileextension = ".swm";          //MSK           "SwarmData"
                            break;

                        case global.TypeID.SWARM_MS:        //SwarmBin
                            fileextension = ".SwarmBin";
                            break;

                        case global.TypeID.XMLBIN_MS:        //XmlBin
                            fileextension = ".XmlBin";
                            break;

                        case global.TypeID.CABXML_MS:        //CABXml
                            fileextension = ".CABXml";
                            break;

                        case global.TypeID.CABBIN_MS:        //CABBin
                            fileextension = ".CABBin";
                            break;

                        case global.TypeID.LIGHTBOXXML_MS:      //LightBoxXml
                            fileextension = ".lightBoxXml";
                            break;

                        case global.TypeID.LIGHTBOXBIN_MS:      //LightBoxBin
                            fileextension = ".lightBoxBin";     //MSK LightBoxData (Named in MSK's executable, though I think I found it in MySims?)
                            break;

                        case global.TypeID.XMB_MS:      //xmb
                            fileextension = ".xmb";
                            break;

                        default:
                            Console.WriteLine("Unknown type ID " + subfiles[i].typeID);
                            Console.WriteLine("and this type ID appears " + GetNumOccurrencesOfTypeID(subfiles[i].typeID) + " times in total.");
                            Console.WriteLine("index of file was " + filesprocessed);
                            fileextension = "." + subfiles[i].typeID.ToString();
                            break;
                        }

                        subfiles[i].fileextension = fileextension;



                        Vault.luaString typeIDRealString = global.activeVault.GetLuaStringWithHash(subfiles[i].typeID);

                        //if (typeIDRealString != null)
                        //   {
                        //   fileextension = "." + typeIDRealString.name;
                        //   }



                        byte[] newfilenameasbytes = BitConverter.GetBytes(Utility.ReverseEndianULong(subfiles[i].hash));

                        subfiles[i].filename = "0x";

                        ulong newfilenameasulong = Utility.ReverseEndianULong(subfiles[i].hash);

                        subfiles[i].hashString = "0x" + BitConverter.ToString(newfilenameasbytes).Replace("-", "");

                        if (global.activeVault.VaultHashesAndFileNames.Keys.Contains(subfiles[i].hash))
                        {
                            subfiles[i].filename = global.activeVault.VaultHashesAndFileNames[subfiles[i].hash];
                        }
                        else
                        {
                            subfiles[i].filename = subfiles[i].hashString;
                        }

                        subfiles[i].filename += fileextension;

                        /*
                         * if (fileextension == ".lua") //temp
                         *  {
                         *  string luaName = "";
                         *
                         *  int currentOffset = 0x10;
                         *
                         *  while (newfile[currentOffset] != 0x00)
                         *      {
                         *      currentOffset++;
                         *      }
                         *
                         *  while (newfile[currentOffset] != 0x2F)
                         *  {
                         *      currentOffset--;
                         *  }
                         *
                         *  currentOffset++;
                         *
                         *  while (newfile[currentOffset] != 0x2E)
                         *      {
                         *      luaName += ((char)newfile[currentOffset]) + "";
                         *      currentOffset++;
                         *      }
                         *
                         *  luaFilenamesForDict.Add("VaultHashesAndFileNames.Add("+newfilename+",\""+luaName+"\");");
                         *  }*/

                        filesprocessed++;
                    }
                }
                form1.MakeFileTree();

                if (containslua && global.activeVault.luaStrings.Count > 0)
                {
                    string[] luaStringsForExport = new string[global.activeVault.luaStrings.Count];

                    for (int i = 0; i < global.activeVault.luaStrings.Count; i++)
                    {
                        luaStringsForExport[i]  = BitConverter.ToString(BitConverter.GetBytes(Utility.ReverseEndian(global.activeVault.luaStrings[i].hash))).Replace("-", "");;
                        luaStringsForExport[i] += " " + global.activeVault.luaStrings[i].name;
                    }

                    File.WriteAllLines("global.activeVault.luaStrings.lua", luaStringsForExport);
                }

                File.WriteAllLines("dict.txt", luaFilenamesForDict);
                MessageBox.Show("Processed " + filesprocessed + " files (out of a total " + filecount + ").", "Task complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Ejemplo n.º 21
0
 public hkxLocalFixupEntry(Subfile basis, int pos)
 {
     destOffset = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
     pos       += 4;
     srcOffset  = Utility.ReverseEndianSigned(BitConverter.ToInt32(basis.filebytes, pos));
 }
Ejemplo n.º 22
0
 public hkArray(Subfile basis, int objectOffset)
 {
     System.Windows.Forms.MessageBox.Show("hkArray not implemented yet");
 }
Ejemplo n.º 23
0
        public RevoModel(Subfile basis)
        {
            int pos = 0;

            magic = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;
            flags = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;

            pos += 0x18;

            int meshcount       = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
            int meshtableoffset = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

            for (int m = 0; m < meshcount; m++)
            {
                Mesh newMesh = new Mesh();

                pos = meshtableoffset + (m * 4);
                int meshInfoTableOffset = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

                pos = meshInfoTableOffset;

                int displayListSize   = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
                int displayListOffset = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
                int numVertAttributes = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
                int vertDataOffset    = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

                newMesh.hash_of_material = Utility.ReadUInt64BigEndian(basis.filebytes, pos); pos += 8;
                uint typeID_of_material = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;
                uint unk2 = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;

                float boundsMinX = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                float boundsMinY = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                float boundsMinZ = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;

                float boundsMaxX = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                float boundsMaxY = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                float boundsMaxZ = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;

                uint unk3 = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;
                uint unk4 = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;

                uint unk5 = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4; //FNV-1 hash of "none" in MySims Kingdom. Different in Agents.

                pos += 12;

                int boneToMatrixBindingInfoOffset = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
                int boneNamesOffset = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;
                int boneInfoOffset  = Utility.ReadInt32BigEndian(basis.filebytes, pos); pos += 4;

                //now read vertex data

                for (int v = 0; v < numVertAttributes; v++)
                {
                    pos = vertDataOffset + (v * 8);

                    VertexAttributeArrayType vertexArrayType = (VertexAttributeArrayType)basis.filebytes[pos]; pos++;
                    //what kind of data is stored in the array: positions? lights? etc.
                    newMesh.presentAttributes.Add(vertexArrayType);

                    VertexAttributeComponentType vertexComponentType = (VertexAttributeComponentType)(basis.filebytes[pos] >> 3);
                    //how many components are there to the data, e.g. is it XYZ, or just XY? etc.

                    VertexAttributeComponentSize vertexComponentSize = (VertexAttributeComponentSize)(basis.filebytes[pos] & 0x07); pos++;
                    //what format is the data in, e.g. 32 bit float, u8, RGB565, etc...

                    pos += 2;                                               //skip padding

                    pos = Utility.ReadInt32BigEndian(basis.filebytes, pos); //now go to the start of the actual entries



                    int stopPoint = boneToMatrixBindingInfoOffset;  //absolute endpoint is the beginning of the next section
                    if (stopPoint == 0)
                    {
                        if (m == meshcount - 1)
                        {
                            stopPoint = basis.filebytes.Length;
                        }
                        else
                        {
                            stopPoint = Utility.ReadInt32BigEndian(basis.filebytes, meshtableoffset + ((m + 1) * 4));
                        }
                    }

                    if (v < numVertAttributes - 1)   //but if we're not at the last vertex array yet, then the endpoint is the start of the next array
                    {
                        stopPoint = Utility.ReadInt32BigEndian(basis.filebytes, vertDataOffset + ((v + 1) * 8) + 4);
                    }

                    int checkAheadAmount = 12;

                    if (vertexArrayType == VertexAttributeArrayType.GX_LIGHTARRAY)   //it will probably ask for RGB values etc
                    {
                        switch (vertexComponentSize)
                        {
                        case VertexAttributeComponentSize.GX_RGBA4:
                            checkAheadAmount = 1;
                            break;

                        case VertexAttributeComponentSize.GX_RGB565:
                            checkAheadAmount = 2;
                            break;

                        case VertexAttributeComponentSize.GX_RGB8:      //more accurately described as RGB24
                        case VertexAttributeComponentSize.GX_RGBA6:     //more accurately described as RGBA24
                            checkAheadAmount = 3;
                            break;

                        case VertexAttributeComponentSize.GX_RGBA8:
                        case VertexAttributeComponentSize.GX_RGBX8:
                            checkAheadAmount = 4;
                            break;
                        }
                    }
                    else
                    {
                        switch (vertexComponentSize)
                        {
                        case VertexAttributeComponentSize.GX_S8:
                        case VertexAttributeComponentSize.GX_U8:
                            checkAheadAmount = 1;
                            break;

                        case VertexAttributeComponentSize.GX_S16:
                        case VertexAttributeComponentSize.GX_U16:
                            checkAheadAmount = 2;
                            break;

                        case VertexAttributeComponentSize.GX_F32:
                            checkAheadAmount = 4;
                            break;
                        }
                    }

                    switch (vertexComponentType)
                    {
                    case VertexAttributeComponentType.GX_POS_XY:
                        checkAheadAmount *= 2;
                        break;

                    case VertexAttributeComponentType.GX_POS_XYZ:
                        checkAheadAmount *= 3;
                        break;

                    default:
                        System.Windows.Forms.MessageBox.Show("Unhandled component type, and therefore couldn't find an appopriate multiplier: " + vertexComponentType);
                        break;
                    }

                    //now actually go and read those vertices

                    List <Vertex> vertexAttributes = new List <Vertex>();

                    do
                    {
                        Vertex newVertex = new Vertex();

                        Console.WriteLine("Loading attribute " + vertexArrayType);

                        if (vertexArrayType == VertexAttributeArrayType.GX_VA_POS)
                        {
                            switch (vertexComponentType)
                            {
                            case VertexAttributeComponentType.GX_POS_XY:

                                if (vertexComponentSize == VertexAttributeComponentSize.GX_F32)
                                {
                                    checkAheadAmount     = 8;
                                    newVertex.position.x = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.position.y = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The vertex coordinates are not floats! How annoying.");
                                }
                                break;

                            case VertexAttributeComponentType.GX_POS_XYZ:

                                if (vertexComponentSize == VertexAttributeComponentSize.GX_F32)
                                {
                                    checkAheadAmount     = 12;
                                    newVertex.position.x = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.position.y = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.position.z = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The vertex coordinates are not floats! How annoying.");
                                }
                                break;

                            default:
                                Console.WriteLine("Unhandled vertex component type: " + vertexComponentType);
                                break;
                            }
                        }
                        else if (vertexArrayType == VertexAttributeArrayType.GX_VA_NRM || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX0 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX1 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX2 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX3 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX4 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX5 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX6 || vertexArrayType == VertexAttributeArrayType.GX_VA_TEX7)
                        {
                            switch (vertexComponentType)
                            {
                            case VertexAttributeComponentType.GX_NRM_XYZ:

                                if (vertexComponentSize == VertexAttributeComponentSize.GX_F32)
                                {
                                    checkAheadAmount   = 12;
                                    newVertex.normal.x = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.y = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.z = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The normal coordinates are not floats! How annoying.");
                                }
                                break;

                            case VertexAttributeComponentType.GX_NRM_NBT3:

                                if (vertexComponentSize == VertexAttributeComponentSize.GX_F32)
                                {
                                    checkAheadAmount     = 36;
                                    newVertex.normal.x   = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.y   = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.z   = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.binormal.x = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.binormal.y = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.binormal.z = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.tangent.x  = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.tangent.y  = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.tangent.z  = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The normal coordinates are not floats! How annoying.");
                                }
                                break;

                            case VertexAttributeComponentType.GX_NRM_NBT:

                                if (vertexComponentSize == VertexAttributeComponentSize.GX_F32)
                                {
                                    checkAheadAmount   = 12;
                                    newVertex.normal.x = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.y = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    newVertex.normal.z = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                }
                                else if (vertexComponentSize == VertexAttributeComponentSize.GX_U8)
                                {
                                    checkAheadAmount = 8;      //APPARENTLY IT IGNORES THE U8 AND READS FLOATS INSTEAD.

                                    float U = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;
                                    float V = Utility.ReadSingleBigEndian(basis.filebytes, pos); pos += 4;

                                    newVertex.UVchannels[(int)vertexArrayType - 13] = new MorcuMath.Vector2(U, V);
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The normal coordinates are not floats! How annoying.");
                                }
                                break;

                            default:
                                Console.WriteLine("Unhandled tex or normal component type: " + vertexComponentType);
                                break;
                            }
                        }
                        else if (vertexArrayType == VertexAttributeArrayType.GX_VA_CLR0 || vertexArrayType == VertexAttributeArrayType.GX_VA_CLR1)
                        {
                            switch (vertexComponentType)
                            {
                            case VertexAttributeComponentType.GX_CLR_RGB:
                                if (vertexComponentSize == VertexAttributeComponentSize.GX_RGBA6)     //RGBA24 basically
                                {
                                    checkAheadAmount = 3;
                                    newVertex.color  = imageTools.ReadRGBA24(basis.filebytes, pos);
                                    pos += 3;
                                }
                                else
                                {
                                    System.Windows.Forms.MessageBox.Show("Argh! The rgb component size was unhandled! It was: " + vertexComponentSize);
                                }
                                break;

                            default:
                                Console.WriteLine("Unhandled colour component type: " + vertexComponentType);
                                break;
                            }
                        }
                        else
                        {
                            Console.WriteLine("Don't know how to read a vertex array of type: " + vertexArrayType + "! Component type is: " + vertexComponentType);
                            break;
                        }

                        vertexAttributes.Add(newVertex);
                    } while (pos + checkAheadAmount <= stopPoint);


                    switch (vertexArrayType)
                    {
                    case VertexAttributeArrayType.GX_VA_POS:
                        newMesh.vertices = vertexAttributes;
                        break;

                    case VertexAttributeArrayType.GX_VA_NRM:
                        foreach (Vertex vn in vertexAttributes)
                        {
                            newMesh.normals.Add(vn);
                        }
                        break;

                    case VertexAttributeArrayType.GX_VA_TEX0:
                        newMesh.texCoords = vertexAttributes;
                        break;
                    }
                }

                //now read display list data

                pos = displayListOffset;

                while (pos < displayListOffset + displayListSize)
                {
                    byte cmd = basis.filebytes[pos]; pos++;

                    switch ((DisplayListCommand)cmd)
                    {
                    case DisplayListCommand.kGXCmdNOP:
                        break;

                    case DisplayListCommand.kGXCmdLoadIndxA:
                    case DisplayListCommand.kGXCmdLoadIndxB:
                    case DisplayListCommand.kGXCmdLoadIndxC:
                    case DisplayListCommand.kGXCmdLoadIndxD:
                        pos += 4;
                        break;

                    default:
                    {
                        byte drawCmd = (byte)((cmd & 0x78) >> 3);
                        byte vat     = (byte)(cmd & 0x07);

                        if (drawCmd > 7)
                        {
                            Console.WriteLine("Invalid Display List command " + cmd + " at offset " + pos);
                        }
                        else
                        {
                            DrawType drawType = (DrawType)drawCmd;

                            //Console.WriteLine("Found drawtype at "+pos+": " + drawType);

                            // Read element amount
                            int elemCount = Utility.ReadUInt16BigEndian(basis.filebytes, pos); pos += 2;

                            switch (drawType)
                            {
                            case DrawType.quads:
                            case DrawType.quads2:
                            case DrawType.triangles:
                                int vertsMax = 4;
                                if (drawType == DrawType.triangles)
                                {
                                    vertsMax = 3;
                                }

                                for (int f = 0; f < elemCount / vertsMax; f++)
                                {
                                    Face newFace = new Face();
                                    for (int i = 0; i < vertsMax; i++)
                                    {
                                        if (boneNamesOffset != 0)
                                        {
                                            switch (i)
                                            {
                                            case 0: newFace.v1BoneIndex = basis.filebytes[pos];  break;

                                            case 1: newFace.v2BoneIndex = basis.filebytes[pos]; break;

                                            case 2: newFace.v3BoneIndex = basis.filebytes[pos]; break;

                                            case 3: newFace.v4BoneIndex = basis.filebytes[pos]; newFace.is_quad = true; break;
                                            }
                                            pos++;
                                        }

                                        for (int attr = 0; attr < 20; attr++)
                                        {              //for each possible vertex attribute, if it exists, process it in order
                                            if (newMesh.presentAttributes.Contains((VertexAttributeArrayType)attr))
                                            {
                                                newFace = AddAttrToFace(basis.filebytes, pos, (VertexAttributeArrayType)attr, newFace, i);
                                                pos     = newFace.temp;
                                            }
                                        }

                                        newMesh.faces.Add(newFace);
                                    }
                                }
                                break;

                            case DrawType.triangleStrip:
                            {
                                Face newFace   = new Face();
                                int  currentV  = 0;
                                int  backupPos = 0;
                                bool winding   = false;

                                for (int i = 0; i < elemCount; i++)
                                {
                                    if (currentV == 1)
                                    {                   //if we're reading the penultimate vertex in a triangle, remember our pos because we'll need to come back to it when we process the next triangle (which overlaps slightly)
                                        backupPos = pos;
                                    }

                                    if (boneNamesOffset != 0)
                                    {
                                        switch (currentV)
                                        {
                                        case 0: newFace.v1BoneIndex = basis.filebytes[pos]; break;

                                        case 1: newFace.v2BoneIndex = basis.filebytes[pos]; break;

                                        case 2: newFace.v3BoneIndex = basis.filebytes[pos]; break;

                                        case 3: newFace.v4BoneIndex = basis.filebytes[pos]; newFace.is_quad = true; break;                      //this won't get triggered by a triangle, but might as well keep it here so I don't forget for quads
                                        }
                                        pos++;
                                    }

                                    if (winding && currentV == 0)
                                    {
                                        currentV = 1;
                                    }
                                    else if (winding && currentV == 1)
                                    {
                                        currentV = 0;
                                    }

                                    for (int attr = 0; attr < 20; attr++)
                                    {                  //for each possible vertex attribute, if it exists, process it in order
                                        if (newMesh.presentAttributes.Contains((VertexAttributeArrayType)attr))
                                        {
                                            newFace = AddAttrToFace(basis.filebytes, pos, (VertexAttributeArrayType)attr, newFace, currentV);
                                            pos     = newFace.temp;
                                        }
                                    }

                                    if (winding && currentV == 1)
                                    {
                                        currentV = 0;
                                    }
                                    else if (winding && currentV == 0)
                                    {
                                        currentV = 1;
                                    }

                                    currentV++;

                                    if (currentV == 3)
                                    {                 //if we just finished making a triangle
                                        newMesh.faces.Add(newFace);
                                        newFace  = new Face();
                                        currentV = 0;
                                        if (i < elemCount - 1)
                                        {                 //as long as we're not on the very last one, there's still work to do so back up a bit and keep reading the strip
                                            i      -= 2;
                                            pos     = backupPos;
                                            winding = !winding;
                                        }
                                    }
                                }
                            }
                            break;

                            default:
                                Console.WriteLine("Unhandled draw type at offset " + pos + ": " + drawType);
                                break;
                            }
                        }
                    }
                    break;
                    }
                }

                //now get the materials ready

                newMesh.materials = new List <MaterialData>();

                if (newMesh.hash_of_material != 0)
                {
                    has_materials = true;
                }

                foreach (Subfile s in global.activePackage.subfiles)
                {
                    if (s.hash == newMesh.hash_of_material && s.typeID == typeID_of_material)
                    {
                        switch ((global.TypeID)s.typeID)
                        {
                        case global.TypeID.MATD_MSK:
                        case global.TypeID.MATD_MSA:

                            if (s.filebytes == null || s.filebytes.Length == 0)
                            {
                                s.Load();
                            }
                            newMesh.materials.Add(s.matd);
                            break;

                        case global.TypeID.MTST_MSK:
                        case global.TypeID.MTST_MSA:
                            if (s.filebytes == null || s.filebytes.Length == 0)
                            {
                                s.Load();
                            }

                            foreach (MaterialData mat in s.mtst.mats)
                            {
                                newMesh.materials.Add(mat);
                            }

                            break;

                        default:
                            System.Windows.Forms.MessageBox.Show("RMDL tried to use a material of unexpected type ID: " + (global.TypeID)s.typeID);
                            break;
                        }
                        break;
                    }
                }

                meshes.Add(newMesh);
            }
        }
Ejemplo n.º 24
0
        public TPLtexture(Subfile basis)
        {
            uint imagesize = 0;

            ushort width  = 0;
            ushort height = 0;

            version = basis.filebytes[5];

            int imageoffset = 0;

            int pos = 0;

            if (global.activePackage.packageType == Package.PackageType.SkyHeroes && Utility.ReadUInt32BigEndian(basis.filebytes, pos) != 0)        //skip those annoying extra headers from MySims SkyHeroes
            {
                startoffile = 0x50;
            }

            pos = startoffile;

            if (global.activePackage.packageType == Package.PackageType.Agents || global.activePackage.packageType == Package.PackageType.Kingdom)
            {
                magic = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                pos  += 4;
                flags = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                pos  += 4;

                if (version == 1)   //MYSIMS
                {
                    pos = 0x1C;

                    width  = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 2;
                    height = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 5;

                    imageformat = (ImageFormat)basis.filebytes[pos];
                    pos++;
                    imagecount = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                    pos       += 4;

                    pos += 0x14;

                    imageoffset = 0x4C;
                    pos        += 4;

                    imagesize = (uint)(height * width * 4);
                }
                else if (version == 2)  //MYSIMS
                {
                    pos = 0x1C;

                    width  = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 2;
                    height = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 5;

                    imageformat = (ImageFormat)basis.filebytes[pos];
                    pos++;
                    imagecount = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                    pos       += 4;

                    pos += 0x14;

                    imageoffset = 0x4C;
                    pos        += 4;

                    imagesize = (uint)(height * width * 4);
                }
                else if (version == 3)   //MYSIMS KINGDOM AND AGENTS
                {
                    imagesize = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                    pos      += 4;

                    pos += 0x0C;

                    width  = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 2;
                    height = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                    pos   += 5;

                    imageformat = (ImageFormat)basis.filebytes[pos];
                    pos++;
                    imagecount = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                    pos       += 4;

                    pos += 0x14;

                    imageoffset = Utility.ReadInt32BigEndian(basis.filebytes, pos);
                    pos        += 4;
                }
            }
            else if (global.activePackage.packageType == Package.PackageType.SkyHeroes)
            {
                magic = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                pos  += 4;
                flags = Utility.ReadUInt32BigEndian(basis.filebytes, pos);
                pos  += 4;

                pos  += 6;
                width = Utility.ReadUInt16BigEndian(basis.filebytes, pos);
                pos  += 2;

                pos   += 2;
                height = Utility.ReadUInt16BigEndian(basis.filebytes, pos);

                pos += 0x2D;

                imageformat = (ImageFormat)basis.filebytes[pos];
                pos        += 1;

                imageoffset = (pos + 0x20) - startoffile;
            }

            if (imagecount == 0)
            {
                imagecount = 1;
            }

            pos = startoffile + imageoffset;

            if (global.activePackage.packageType == Package.PackageType.SkyHeroes)
            {
                imagesize = (uint)((basis.filebytes.Length - startoffile) - (pos - startoffile));
            }

            while ((width % 8) != 0)
            {
                width++;
            }

            while ((height % 8) != 0)
            {
                height++;
            }

            for (int img = 0; img < imagecount; img++)
            {
                Bitmap newImage = new Bitmap(width, height);

                switch (imageformat)
                {
                case ImageFormat.CMPR:
                    for (int y = 0; y < height; y += 8)
                    {
                        for (int x = 0; x < width; x += 8)
                        {
                            for (int j = 0; j < 4; j++)
                            {
                                if ((j == 1 || j == 3) && ((x + 4) >= width))
                                {
                                    continue;
                                }
                                if ((j == 2 || j == 3) && ((y + 4) >= height))
                                {
                                    continue;
                                }

                                Color[] cols = new Color[4];

                                ushort col0ushort = Utility.ReadUInt16BigEndian(basis.filebytes, pos); pos += 2;
                                ushort col1ushort = Utility.ReadUInt16BigEndian(basis.filebytes, pos); pos += 2;
                                cols[0] = imageTools.ToRGB565(col0ushort);
                                cols[1] = imageTools.ToRGB565(col1ushort);

                                cols[2] = new Color();
                                cols[3] = new Color();

                                if (col0ushort > col1ushort)
                                {
                                    cols[2] = Color.FromArgb(255, ((2 * cols[0].R) + (cols[1].R)) / 3, ((2 * cols[0].G) + (cols[1].G)) / 3, ((2 * cols[0].B) + (cols[1].B)) / 3);
                                    cols[3] = Color.FromArgb(255, ((2 * cols[1].R) + (cols[0].R)) / 3, ((2 * cols[1].G) + (cols[0].G)) / 3, ((2 * cols[1].B) + (cols[0].B)) / 3);
                                }
                                else
                                {
                                    cols[2] = Color.FromArgb(255, (cols[0].R + cols[1].R) / 2, (cols[0].G + cols[1].G) / 2, (cols[0].B + cols[1].B) / 2);
                                    cols[3] = Color.FromArgb(0, 0, 0, 0);
                                }

                                uint indices = Utility.ReadUInt32BigEndian(basis.filebytes, pos); pos += 4;

                                int xOffset = 0;
                                int yOffset = 0;

                                switch (j)
                                {
                                case 0: xOffset = 0; yOffset = 0; break;

                                case 1: xOffset = 4; yOffset = 0; break;

                                case 2: xOffset = 0; yOffset = 4; break;

                                case 3: xOffset = 4; yOffset = 4; break;
                                }

                                int xOffsetLimit = xOffset + 3;


                                for (int i = 30; i >= 0; i -= 2)
                                {
                                    newImage.SetPixel(x + xOffset, y + yOffset, cols[(indices >> i) & 0x03]);
                                    xOffset++;
                                    if (xOffset > xOffsetLimit)
                                    {
                                        xOffset -= 4;
                                        yOffset++;
                                    }
                                }
                            }
                        }
                    }
                    break;

                case ImageFormat.RGBA32:
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            int xOffset = 0;
                            int yOffset = 0;
                            for (int j = 0; j < 16; j++)
                            {
                                newImage.SetPixel(x + xOffset, y + yOffset, imageTools.ReadNintendoRGBA32(basis.filebytes, pos));
                                pos += 2;
                                xOffset++;

                                if (xOffset > 3)
                                {
                                    xOffset = 0;
                                    yOffset++;
                                }
                            }

                            pos += 0x20;
                        }
                    }
                    break;

                default:
                    Console.WriteLine("That image format was not handled by the switch statement! Image format was: " + imageformat);
                    break;
                }
                images.Add(newImage);
            }
        }
Ejemplo n.º 25
0
        public MsaCollision(Subfile basis)
        {
            obj             = new List <string>();
            cumulativeVerts = 0;

            if (basis.filebytes.Length == 0)
            {
                Console.WriteLine("Couldn't process the MSA collision file because the input subfile was empty.");
                return;
            }

            int meshDataOffset = Utility.ReadInt32BigEndian(basis.filebytes, 0x14);

            int pos = meshDataOffset + 0x08;
            int offsetOfEndOfMeshData = meshDataOffset + Utility.ReadInt32BigEndian(basis.filebytes, pos);

            pos = meshDataOffset + 0x10;
            int sectionCount = Utility.ReadInt32BigEndian(basis.filebytes, pos);

            pos += 4;

            int[] sectionOffsets = new int[sectionCount];

            for (int i = 0; i < sectionCount; i++)
            {
                sectionOffsets[i] = meshDataOffset + Utility.ReadInt32BigEndian(basis.filebytes, pos + (i * 4));
            }

            //section 0 is some other data, the rest are vertex data seemingly

            pos = sectionOffsets[0];

            //deal with section 0 here

            //now deal with other sections

            for (int i = 1; i < sectionCount; i++)
            {
                //seems to be triangle coordinates where each one overlaps at the end, then the section is terminated with 0x00000001

                obj.Add("o object" + i);
                pos = sectionOffsets[i];

                float UnkMultiplier = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float xUnk = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float yUnk = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float zUnk = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;


                float Unk2Multiplier = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float xUnk2 = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float yUnk2 = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float zUnk2 = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;


                float nudgeMultiplier = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float xNudge = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float yNudge = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;
                float zNudge = Utility.ReadSingleBigEndian(basis.filebytes, pos);
                pos += 4;

                pos += 12;


                while (pos < basis.filebytes.Length && Utility.ReadInt32BigEndian(basis.filebytes, pos) != 1)
                {
                    int chunkType = Utility.ReadInt32BigEndian(basis.filebytes, pos);
                    pos += 4;

                    Console.WriteLine("MSA collision chunk " + chunkType + " at " + pos);
                    switch (chunkType)
                    {
                    case 0x04:
                        //extents X Y Z of collision box
                        vertices.Add(new Vertex(Utility.ReadSingleBigEndian(basis.filebytes, pos), Utility.ReadSingleBigEndian(basis.filebytes, pos + 4), Utility.ReadSingleBigEndian(basis.filebytes, pos + 8)));
                        pos += 12;
                        pos += 12;     //seems to be a hash of a lua attribute or two? Possibly giving a name to this particular bit of collision. No obvious effects when nulled out (although there might be if the object is required by a lua script)
                        break;

                    default:
                        Console.WriteLine("Unhandled MSA collision chunk type: " + chunkType);
                        obj.Add("#dodgy");
                        break;
                    }
                }

                foreach (Vertex v in vertices)
                {
                    obj.Add("v " + v.position.x + " " + v.position.y + " " + v.position.z);
                }

                vertices.Clear();

                cumulativeVerts += vertices.Count;
            }
        }
Ejemplo n.º 26
0
        public void backtrackSubfile(Subfile s)
        {
            Console.WriteLine("Backtracking " + s.filename);

            switch ((global.TypeID)s.typeID)
            {
            case global.TypeID.TPL_MSK:
            case global.TypeID.TPL_MSA:
                foreach (Subfile superior in global.activePackage.subfiles)
                {
                    //look for MATDs that reference this texture

                    if ((global.TypeID)superior.typeID == global.TypeID.MATD_MSK || (global.TypeID)superior.typeID == global.TypeID.MATD_MSA)
                    {
                        superior.Load();
                        foreach (MaterialData.Param param in superior.matd.parameters)
                        {
                            if (param.paramType == MaterialData.MaterialParameter.diffuseMap && param.diffuse_texture == s)
                            {
                                backtrackSubfile(superior);
                                return;
                            }
                        }
                        superior.Unload();
                    }
                }
                break;

            case global.TypeID.MTST_MSK:
            case global.TypeID.MTST_MSA:
                foreach (Subfile superior in global.activePackage.subfiles)
                {
                    //look for RMDLs that reference this materialset

                    if ((global.TypeID)superior.typeID == global.TypeID.RMDL_MSK || (global.TypeID)superior.typeID == global.TypeID.RMDL_MSA)
                    {
                        superior.Load();

                        foreach (RevoModel.Mesh m in superior.rmdl.meshes)
                        {
                            if (m.hash_of_material == s.hash)
                            {
                                MessageBox.Show("Succesfully backtracked to model: " + superior.filename);

                                foreach (TreeNode node in FileTree.Nodes[0].Nodes)
                                {
                                    if (treeNodesAndSubfiles[node] == superior)
                                    {
                                        FileTree.SelectedNode = node;
                                        break;
                                    }
                                }
                                FileTree.SelectedNode.EnsureVisible();
                                return;
                            }
                        }

                        superior.Unload();
                    }
                }
                break;

            case global.TypeID.MATD_MSK:
            case global.TypeID.MATD_MSA:
                foreach (Subfile superior in global.activePackage.subfiles)
                {
                    //look for RMDLs and MTSTs that reference this material

                    if ((global.TypeID)superior.typeID == global.TypeID.RMDL_MSK || (global.TypeID)superior.typeID == global.TypeID.RMDL_MSA ||
                        (global.TypeID)superior.typeID == global.TypeID.MTST_MSK || (global.TypeID)superior.typeID == global.TypeID.MTST_MSA)
                    {
                        superior.Load();

                        if (superior.rmdl != null)
                        {
                            foreach (RevoModel.Mesh m in superior.rmdl.meshes)
                            {
                                if (m.materials.Contains(s.matd))
                                {
                                    MessageBox.Show("Succesfully backtracked to model: " + superior.filename);

                                    foreach (TreeNode node in FileTree.Nodes[0].Nodes)
                                    {
                                        if (treeNodesAndSubfiles[node] == superior)
                                        {
                                            FileTree.SelectedNode = node;
                                            break;
                                        }
                                    }
                                    FileTree.SelectedNode.EnsureVisible();
                                    return;
                                }
                            }
                        }
                        else if (superior.mtst != null)
                        {
                            if (superior.mtst.mats.Contains(s.matd))
                            {
                                backtrackSubfile(superior);
                                return;
                            }
                        }

                        superior.Unload();
                    }
                }
                break;

            default:
                MessageBox.Show("Sorry, that type of file is not applicable for backtracking.");
                break;
            }
        }