Example #1
0
        private static void UpdateMTLS(BinaryReader br, BinaryWriter bw, int size)
        {
            Console.WriteLine("'Fixing' MTLS");

            // write the header and record the chunk size offset
            bw.Write((int)Chunks.MTLS);
            long offset = bw.BaseStream.Position;

            bw.Write(0);

            long end = br.BaseStream.Position + size;

            while (br.BaseStream.Position < end)
            {
                using (var substream = new SubStream())
                {
                    substream.Write(br.ReadBytes(12));  // inclusive size, PriorityPlane Flags

                    br.BaseStream.Position += SizeName; // skip Shader

                    // write then write LAYS
                    br.AssertTag("LAYS");
                    int layerCount = br.ReadInt32();
                    substream.Write((int)Chunks.LAYS);
                    substream.Write(layerCount);

                    for (int i = 0; i < layerCount; i++)
                    {
                        using (var layerstream = new SubStream())
                        {
                            long laysEnd = br.BaseStream.Position + br.ReadInt32();

                            br.BaseStream.Position -= 4;
                            layerstream.Write(br.ReadBytes(28)); // size, BlendMode, flags, textureid, textureanimationid, coordid, alpha

                            br.BaseStream.Position += 4;         // skip EmissiveGain

                            while (br.BaseStream.Position != laysEnd)
                            {
                                long start = br.BaseStream.Position;

                                string tag               = br.ReadString(4);
                                int    trackCount        = br.ReadInt32();
                                int    interpolationType = br.ReadInt32();
                                int    totalSize         = 16 + (trackCount * (interpolationType <= 1 ? 8 : 16)); // calc size of the whole track

                                br.BaseStream.Position = start;
                                if (tag == "KMTE")
                                {
                                    br.BaseStream.Position += totalSize; // skip
                                }
                                else
                                {
                                    layerstream.Write(br.ReadBytes(totalSize)); // clone track
                                }
                            }

                            // update the LAYS inclusive size
                            layerstream.Position = 0;
                            layerstream.Write((int)layerstream.Length);
                            layerstream.WriteTo(substream);
                        }
                    }

                    // update the Material inclusive size
                    substream.Position = 0;
                    substream.Write((int)substream.Length);
                    substream.WriteTo(bw.BaseStream);
                }
            }

            // update the MTLS chunk size
            bw.BaseStream.Position = offset;
            bw.Write((int)(bw.BaseStream.Length - offset - 4));
            bw.BaseStream.Position = bw.BaseStream.Length;
        }
Example #2
0
        private static void UpdateGEOS(BinaryReader br, BinaryWriter bw, int size)
        {
            Console.WriteLine("'Fixing' GEOS");

            // write the header and record the chunk size offset
            bw.Write((uint)Chunks.GEOS);
            long offset = bw.BaseStream.Position;

            bw.Write(0);

            long end = br.BaseStream.Position + size;

            while (br.BaseStream.Position < end)
            {
                using (var substream = new SubStream())
                {
                    long sectionEnd = br.BaseStream.Position + br.ReadInt32();
                    substream.Write(0); // inclusive size

                    int  vertexCount = 0;
                    long gndxOffset  = 0;

                    int noOf = 0;
                    if (br.HasTag("VRTX"))
                    {
                        vertexCount             = noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 12 * noOf));
                    }

                    if (br.HasTag("NRMS"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 12 * noOf));
                    }

                    if (br.HasTag("PTYP"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("PCNT"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("PVTX"))
                    {
                        noOf = br.ReadInt32() / 3;
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 6 * noOf));
                    }

                    if (br.HasTag("GNDX"))
                    {
                        noOf = br.ReadInt32();
                        substream.Write((int)Chunks.GNDX);

                        if (noOf == 0) // this has been moved to the SKIN section
                        {
                            substream.Write(vertexCount);
                            gndxOffset = substream.Position;
                            substream.Write(new byte[vertexCount]);
                        }
                        else
                        {
                            substream.Write(noOf);
                            substream.Write(br.ReadBytes(noOf));
                        }
                    }

                    if (br.HasTag("MTGC"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("MATS"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    substream.Write(br.ReadBytes(12));      // MaterialId, SelectionGroup, Unselectable

                    br.BaseStream.Position += 4 + SizeName; // skip LevelOfDetail, FilePath

                    substream.Write(br.ReadBytes(28));      // Bounds

                    noOf = br.ReadInt32();                  // Extents
                    br.BaseStream.Position -= 4;
                    substream.Write(br.ReadBytes(4 + noOf * 28));

                    if (br.HasTag("TANG"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position += noOf * 16; // skip Tangents
                    }

                    if (br.HasTag("SKIN"))
                    {
                        noOf = br.ReadInt32();

                        // rebuild the GNDX from the SKIN section
                        // this is (uint32 index, uint32 weight)
                        // casting the indicies to bytes is "enough" for this
                        if (gndxOffset > 0)
                        {
                            byte[] buffer = br.ReadBytes(noOf);
                            substream.Position = gndxOffset;
                            for (int i = 0; i < buffer.Length; i += 8)
                            {
                                substream.WriteByte(buffer[i]);
                            }
                            substream.Position = substream.Length;
                        }
                        else
                        {
                            br.BaseStream.Position += noOf;
                        }
                    }

                    // copy anything else the chunk contains
                    int remaining = (int)(sectionEnd - br.BaseStream.Position);
                    if (remaining > 0)
                    {
                        substream.Write(br.ReadBytes(remaining));
                    }

                    // update the inclusive size and write to the filestream
                    substream.Position = 0;
                    substream.Write((int)substream.Length);
                    substream.WriteTo(bw.BaseStream);
                }
            }

            // update the chunk size
            bw.BaseStream.Position = offset;
            bw.Write((int)(bw.BaseStream.Length - offset - 4));
            bw.BaseStream.Position = bw.BaseStream.Length;
        }