/// <summary>
        /// Deserializes file data from a stream.
        /// </summary>
        protected override void Read(BinaryReaderEx br)
        {
            br.BigEndian = false;

            br.AssertASCII("MSB ");
            br.AssertInt32(1);
            br.AssertInt32(0x10);
            br.AssertBoolean(false); // isBigEndian
            br.AssertBoolean(false); // isBitBigEndian
            br.AssertByte(1);        // textEncoding
            br.AssertByte(0xFF);     // is64BitOffset

            Entries entries = default;

            Models             = new ModelParam();
            entries.Models     = Models.Read(br);
            Events             = new EventParam();
            entries.Events     = Events.Read(br);
            Regions            = new PointParam();
            entries.Regions    = Regions.Read(br);
            Routes             = new RouteParam();
            entries.Routes     = Routes.Read(br);
            Layers             = new LayerParam();
            entries.Layers     = Layers.Read(br);
            Parts              = new PartsParam();
            entries.Parts      = Parts.Read(br);
            PartsPoses         = new MapstudioPartsPose();
            entries.PartsPoses = PartsPoses.Read(br);
            BoneNames          = new MapstudioBoneName();
            entries.BoneNames  = BoneNames.Read(br);

            if (br.Position != 0)
            {
                throw new InvalidDataException("The next param offset of the final param should be 0, but it wasn't.");
            }

            MSB.DisambiguateNames(entries.Models);
            MSB.DisambiguateNames(entries.Parts);
            MSB.DisambiguateNames(entries.Regions);

            foreach (Event evt in entries.Events)
            {
                evt.GetNames(this, entries);
            }
            foreach (Region region in entries.Regions)
            {
                region.GetNames(this, entries);
            }
            foreach (Part part in entries.Parts)
            {
                part.GetNames(this, entries);
            }
            foreach (PartsPose pose in entries.PartsPoses)
            {
                pose.GetNames(this, entries);
            }
        }
 /// <summary>
 /// Creates a new MSB3 with all sections empty.
 /// </summary>
 public MSB3()
 {
     Models     = new ModelParam();
     Events     = new EventParam();
     Regions    = new PointParam();
     Routes     = new RouteParam();
     Layers     = new LayerParam();
     Parts      = new PartsParam();
     PartsPoses = new MapstudioPartsPose();
     BoneNames  = new MapstudioBoneName();
 }