示例#1
0
 public void Unpack(CustomPlayback obj)
 {
     if (obj.uniqueID != obj_id)
     {
         Debug.LogError("Cannot unpack recording state to unmatched object");
         return;
     }
     else
     {
         obj.transform.position = pos;
         obj.transform.rotation = rot;
         obj.gameObject.SetActive(enabled);
     }
 }
示例#2
0
        public void WriteToMapStream(BinaryWriter writer, IList <string> strings, int magic)
        {
            int currentEnd;

            unchecked
            {
                magic     += (int)writer.BaseStream.Position;
                currentEnd = MetaRootSize + magic;
            }

            // tier 0
            writer.Write(playbackParameters.Count);
            writer.Write(currentEnd);
            currentEnd += playbackParameters.Count * Marshal.SizeOf(typeof(Playback));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(scales.Count);
            writer.Write(currentEnd);
            currentEnd += scales.Count * Marshal.SizeOf(typeof(Scale));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(importNames.Count);
            writer.Write(currentEnd);
            currentEnd += importNames.Count * Marshal.SizeOf(typeof(ImportName));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(pitchRangeParameters.Count);
            writer.Write(currentEnd);
            currentEnd += pitchRangeParameters.Count * Marshal.SizeOf(typeof(PitchRangeParametersBlock));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(pitchRanges.Count);
            writer.Write(currentEnd);
            currentEnd += pitchRanges.Count * Marshal.SizeOf(typeof(PitchRange));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(permutations.Count);
            writer.Write(currentEnd);
            currentEnd += permutations.Count * Marshal.SizeOf(typeof(Permutation));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(customPlaybacks.Count);
            writer.Write(currentEnd);
            currentEnd += customPlaybacks.Count * Marshal.SizeOf(typeof(CustomPlayback));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(runtimeFlags.Count);
            writer.Write(currentEnd);
            currentEnd += runtimeFlags.Count * Marshal.SizeOf(typeof(RuntimePermutationFlags));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(chunks.Count);
            writer.Write(currentEnd);
            currentEnd += chunks.Count * Marshal.SizeOf(typeof(Chunk));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(promotions.Count);
            writer.Write(currentEnd);
            currentEnd += promotions.Count * Marshal.SizeOf(typeof(Promotion));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            writer.Write(extraInfos.Count);
            writer.Write(currentEnd);
            currentEnd += extraInfos.Count * Marshal.SizeOf(typeof(ExtraInfo));
            currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);

            // tier 1
            for (int i = 0; i < playbackParameters.Count; i++)
            {
                writer.Write(Reinterpret.Object <Playback>(playbackParameters[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < scales.Count; i++)
            {
                writer.Write(Reinterpret.Object <Scale>(scales[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < importNames.Count; i++)
            {
                ImportName importName = new ImportName();
                short      index      = (short)strings.IndexOf(importNames[i]);
                if (index >= 0)
                {
                    importName.Index = index;
                    importName.Size  = (byte)importNames[i].Length;
                }
                writer.Write(Reinterpret.Object <ImportName>(importName));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < pitchRangeParameters.Count; i++)
            {
                writer.Write(Reinterpret.Object <PitchRangeParametersBlock>(pitchRangeParameters[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < pitchRanges.Count; i++)
            {
                writer.Write(Reinterpret.Object <PitchRange>(pitchRanges[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < permutations.Count; i++)
            {
                writer.Write(Reinterpret.Object <Permutation>(permutations[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < customPlaybacks.Count; i++)
            {
                CustomPlayback customPlayback = customPlaybacks[i];

                if (customPlayback.FilterCount > 0)
                {
                    customPlayback.FilterOffset = currentEnd;
                    currentEnd += customPlayback.FilterCount * Marshal.SizeOf(typeof(CustomPlayback.Filter));
                    currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);
                }
                else
                {
                    customPlayback.FilterOffset = 0;
                }

                if (customPlayback.PitchPlaybackParametersCount > 0)
                {
                    customPlayback.PitchPlaybackParametersOffset = currentEnd;
                    currentEnd += customPlayback.PitchPlaybackParametersCount * Marshal.SizeOf(typeof(CustomPlayback.PitchPlaybackParameters));
                    currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);
                }
                else
                {
                    customPlayback.PitchPlaybackParametersOffset = 0;
                }

                writer.Write(Reinterpret.Object <CustomPlayback>(customPlayback));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < runtimeFlags.Count; i++)
            {
                writer.Write(Reinterpret.Object <RuntimePermutationFlags>(runtimeFlags[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < chunks.Count; i++)
            {
                writer.Write(Reinterpret.Object <Chunk>(chunks[i]));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < promotions.Count; i++)
            {
                Promotion promotion = promotions[i];

                if (promotion.RuleCount > 0)
                {
                    promotion.RuleOffset = currentEnd;
                    currentEnd          += promotion.RuleCount * Marshal.SizeOf(typeof(Promotion.Rule));
                    currentEnd           = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);
                }
                else
                {
                    promotion.RuleOffset = 0;
                }

                if (promotion.TimerCount > 0)
                {
                    promotion.TimerOffset = currentEnd;
                    currentEnd           += promotion.TimerCount * Marshal.SizeOf(typeof(Promotion.Timer));
                    currentEnd            = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);
                }
                else
                {
                    promotion.TimerOffset = 0;
                }

                writer.Write(Reinterpret.Object <Promotion>(promotion));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            for (int i = 0; i < extraInfos.Count; i++)
            {
                ExtraInfo extraInfo = extraInfos[i];

                if (extraInfo.ResourceBlock.ResourceCount > 0)
                {
                    extraInfo.ResourceBlock.ResourceOffset = currentEnd;
                    currentEnd += extraInfo.ResourceBlock.ResourceCount * Marshal.SizeOf(typeof(ResourceBlock.Resource));
                    currentEnd  = Alignment.Align(currentEnd, AlignmentConstants.BlockAlignment);
                }
                else
                {
                    extraInfo.ResourceBlock.ResourceOffset = 0;
                }

                writer.Write(Reinterpret.Object <ExtraInfo>(extraInfo));
            }
            writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);

            // tier 2
            for (int i = 0; i < customPlaybacks.Count; i++)
            {
                for (int j = 0; j < customPlaybacks[i].FilterCount; j++)
                {
                    writer.Write(Reinterpret.Object <CustomPlayback.Filter>(customFilters[i][j]));
                }
                writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);
                for (int j = 0; j < customPlaybacks[i].PitchPlaybackParametersCount; j++)
                {
                    writer.Write(Reinterpret.Object <CustomPlayback.PitchPlaybackParameters>(customPitchParameters[i][j]));
                }
                writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);
            }

            for (int i = 0; i < promotions.Count; i++)
            {
                for (int j = 0; j < promotions[i].RuleCount; j++)
                {
                    writer.Write(Reinterpret.Object <Promotion.Rule>(promotionRules[i][j]));
                }
                writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);
                for (int j = 0; j < promotions[i].TimerCount; j++)
                {
                    writer.Write(Reinterpret.Object <Promotion.Timer>(promotionTimers[i][j]));
                }
                writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);
            }

            for (int i = 0; i < extraInfos.Count; i++)
            {
                for (int j = 0; j < extraInfos[i].ResourceBlock.ResourceCount; j++)
                {
                    writer.Write(Reinterpret.Object <ResourceBlock.Resource>(extraInfoResources[i][j]));
                }
                writer.BaseStream.Position = Alignment.Align((int)writer.BaseStream.Position, AlignmentConstants.BlockAlignment);
            }
        }
示例#3
0
        /// <summary>
        /// Creates a new instance of the Coconuts class and reads its values from a coconuts tag.
        /// </summary>
        public Coconuts(BinaryReader reader, SharedMaps maps, int magic, string[] strings)
        {
            #region header
            int playbackCount             = reader.ReadInt32();
            int playbackOffset            = unchecked (reader.ReadInt32() - magic);
            int scaleCount                = reader.ReadInt32();
            int scaleOffset               = unchecked (reader.ReadInt32() - magic);
            int nameCount                 = reader.ReadInt32();
            int nameOffset                = unchecked (reader.ReadInt32() - magic);
            int pitchRangeParameterCount  = reader.ReadInt32();
            int pitchRangeParameterOffset = unchecked (reader.ReadInt32() - magic);
            int pitchRangeCount           = reader.ReadInt32();
            int pitchRangeOffset          = unchecked (reader.ReadInt32() - magic);
            int permutationCount          = reader.ReadInt32();
            int permutationOffset         = unchecked (reader.ReadInt32() - magic);
            int customPlaybackCount       = reader.ReadInt32();
            int customPlaybackOffset      = unchecked (reader.ReadInt32() - magic);
            int runtimeFlagsCount         = reader.ReadInt32();
            int runtimeFlagsOffset        = unchecked (reader.ReadInt32() - magic);
            int chunkCount                = reader.ReadInt32();
            int chunkOffset               = unchecked (reader.ReadInt32() - magic);
            int promotionCount            = reader.ReadInt32();
            int promotionOffset           = unchecked (reader.ReadInt32() - magic);
            int extraInfoCount            = reader.ReadInt32();
            int extraInfoOffset           = unchecked (reader.ReadInt32() - magic);

            if (playbackCount > 0)
            {
                reader.BaseStream.Position = playbackOffset;
            }
            playbackParameters = new List <Playback>(playbackCount);
            for (int i = 0; i < playbackCount; i++)
            {
                playbackParameters.Add(Reinterpret.Memory <Playback>(reader.ReadBytes(Marshal.SizeOf(typeof(Playback)))));
            }

            if (scaleCount > 0)
            {
                reader.BaseStream.Position = scaleOffset;
            }
            scales = new List <Scale>(scaleCount);
            for (int i = 0; i < scaleCount; i++)
            {
                scales.Add(Reinterpret.Memory <Scale>(reader.ReadBytes(Marshal.SizeOf(typeof(Scale)))));
            }

            if (nameCount > 0)
            {
                reader.BaseStream.Position = nameOffset;
            }
            importNames = new List <string>(nameCount);
            for (int i = 0; i < nameCount; i++)
            {
                importNames.Add(strings[reader.ReadInt16()]);
                reader.BaseStream.Position += 2;
            }

            if (pitchRangeParameterCount > 0)
            {
                reader.BaseStream.Position = pitchRangeParameterOffset;
            }
            pitchRangeParameters = new List <PitchRangeParametersBlock>(pitchRangeParameterCount);
            for (int i = 0; i < pitchRangeParameterCount; i++)
            {
                pitchRangeParameters.Add(Reinterpret.Memory <PitchRangeParametersBlock>(reader.ReadBytes(Marshal.SizeOf(typeof(PitchRangeParametersBlock)))));
            }

            if (pitchRangeCount > 0)
            {
                reader.BaseStream.Position = pitchRangeOffset;
            }
            pitchRanges = new List <PitchRange>(pitchRangeCount);
            for (int i = 0; i < pitchRangeCount; i++)
            {
                pitchRanges.Add(Reinterpret.Memory <PitchRange>(reader.ReadBytes(Marshal.SizeOf(typeof(PitchRange)))));
            }

            if (permutationCount > 0)
            {
                reader.BaseStream.Position = permutationOffset;
            }
            permutations = new List <Permutation>(permutationCount);
            for (int i = 0; i < permutationCount; i++)
            {
                permutations.Add(Reinterpret.Memory <Permutation>(reader.ReadBytes(Marshal.SizeOf(typeof(Permutation)))));
            }

            if (customPlaybackCount > 0)
            {
                reader.BaseStream.Position = customPlaybackOffset;
            }
            customPlaybacks = new List <CustomPlayback>(customPlaybackCount);
            for (int i = 0; i < customPlaybackCount; i++)
            {
                CustomPlayback customPlayback = Reinterpret.Memory <CustomPlayback>(reader.ReadBytes(Marshal.SizeOf(typeof(CustomPlayback))));
                unchecked
                {
                    customPlayback.FilterOffset -= magic;
                    customPlayback.FilterPlaybackParametersOffset -= magic;
                    customPlayback.MixFlagsOffset -= magic;
                    customPlayback.PitchPlaybackParametersOffset -= magic;
                    customPlayback.SoundEffectOffset             -= magic;
                }
                customPlaybacks.Add(customPlayback);
            }

            if (runtimeFlagsCount > 0)
            {
                reader.BaseStream.Position = runtimeFlagsOffset;
            }
            runtimeFlags = new List <RuntimePermutationFlags>(runtimeFlagsCount);
            for (int i = 0; i < runtimeFlagsCount; i++)
            {
                runtimeFlags.Add(Reinterpret.Memory <RuntimePermutationFlags>(reader.ReadBytes(Marshal.SizeOf(typeof(RuntimePermutationFlags)))));
            }

            if (chunkCount > 0)
            {
                reader.BaseStream.Position = chunkOffset;
            }
            chunks = new List <Chunk>(chunkCount);
            for (int i = 0; i < chunkCount; i++)
            {
                chunks.Add(Reinterpret.Memory <Chunk>(reader.ReadBytes(Marshal.SizeOf(typeof(Chunk)))));
            }

            if (promotionCount > 0)
            {
                reader.BaseStream.Position = promotionOffset;
            }
            promotions = new List <Promotion>(promotionCount);
            for (int i = 0; i < promotionCount; i++)
            {
                Promotion promotion = Reinterpret.Memory <Promotion>(reader.ReadBytes(Marshal.SizeOf(typeof(Promotion))));
                unchecked
                {
                    promotion.RuleOffset  -= magic;
                    promotion.TimerOffset -= magic;
                }
                promotions.Add(promotion);
            }

            if (extraInfoCount > 0)
            {
                reader.BaseStream.Position = extraInfoOffset;
            }
            extraInfos = new List <ExtraInfo>(extraInfoCount);
            for (int i = 0; i < extraInfoCount; i++)
            {
                ExtraInfo extraInfo = Reinterpret.Memory <ExtraInfo>(reader.ReadBytes(Marshal.SizeOf(typeof(ExtraInfo))));
                extraInfo.ResourceBlock.ResourceOffset = unchecked (extraInfo.ResourceBlock.ResourceOffset - magic);
                extraInfos.Add(extraInfo);
            }
            #endregion

            #region custom playbacks
            customFilters         = new List <List <CustomPlayback.Filter> >(customPlaybackCount);
            customPitchParameters = new List <List <CustomPlayback.PitchPlaybackParameters> >(customPlaybackCount);

            for (int i = 0; i < customPlaybackCount; i++)
            {
                customFilters.Add(new List <CustomPlayback.Filter>(customPlaybacks[i].FilterCount));
                if (customPlaybacks[i].FilterCount > 0)
                {
                    reader.BaseStream.Position = customPlaybacks[i].FilterOffset;
                }
                for (int j = 0; j < customPlaybacks[i].FilterCount; j++)
                {
                    customFilters[i].Add(Reinterpret.Memory <CustomPlayback.Filter>(reader.ReadBytes(Marshal.SizeOf(typeof(CustomPlayback.Filter)))));
                }

                customPitchParameters.Add(new List <CustomPlayback.PitchPlaybackParameters>(customPlaybacks[i].PitchPlaybackParametersCount));
                if (customPlaybacks[i].PitchPlaybackParametersCount > 0)
                {
                    reader.BaseStream.Position = customPlaybacks[i].PitchPlaybackParametersOffset;
                }
                for (int j = 0; j < customPlaybacks[i].PitchPlaybackParametersCount; j++)
                {
                    customPitchParameters[i].Add(Reinterpret.Memory <CustomPlayback.PitchPlaybackParameters>(reader.ReadBytes(Marshal.SizeOf(typeof(CustomPlayback.PitchPlaybackParameters)))));
                }
            }
            #endregion

            #region promotions
            promotionRules  = new List <List <Promotion.Rule> >(promotionCount);
            promotionTimers = new List <List <Promotion.Timer> >(promotionCount);

            for (int i = 0; i < promotionCount; i++)
            {
                promotionRules.Add(new List <Promotion.Rule>(promotions[i].RuleCount));
                if (promotions[i].RuleCount > 0)
                {
                    reader.BaseStream.Position = promotions[i].RuleOffset;
                }
                for (int j = 0; j < promotions[i].RuleCount; j++)
                {
                    promotionRules[i].Add(Reinterpret.Memory <Promotion.Rule>(reader.ReadBytes(Marshal.SizeOf(typeof(Promotion.Rule)))));
                }

                promotionTimers.Add(new List <Promotion.Timer>(promotions[i].TimerCount));
                if (promotions[i].TimerCount > 0)
                {
                    reader.BaseStream.Position = promotions[i].TimerOffset;
                }
                for (int j = 0; j < promotions[i].TimerCount; j++)
                {
                    promotionTimers[i].Add(Reinterpret.Memory <Promotion.Timer>(reader.ReadBytes(Marshal.SizeOf(typeof(Promotion.Timer)))));
                }
            }
            #endregion

            #region extra infos
            extraInfoData      = new List <byte[]>(extraInfoCount);
            extraInfoResources = new List <List <ResourceBlock.Resource> >(extraInfoCount);

            for (int i = 0; i < extraInfoCount; i++)
            {
                extraInfoData.Add(new byte[extraInfos[i].ResourceBlock.RawSize]);
                if (extraInfos[i].ResourceBlock.RawSize > 0)
                {
                    BinaryReader rawReader = maps.GetMap(extraInfos[i].ResourceBlock.RawOffset, reader);
                    if (rawReader != null)
                    {
                        for (int j = 0; j < extraInfos[i].ResourceBlock.RawSize; j++)
                        {
                            extraInfoData[i][j] = rawReader.ReadByte();
                        }
                    }

                    extraInfoResources.Add(new List <ResourceBlock.Resource>(extraInfos[i].ResourceBlock.ResourceCount));
                    if (extraInfos[i].ResourceBlock.ResourceCount > 0)
                    {
                        reader.BaseStream.Position = extraInfos[i].ResourceBlock.ResourceOffset;
                    }
                    for (int j = 0; j < extraInfos[i].ResourceBlock.ResourceCount; j++)
                    {
                        extraInfoResources[i].Add(Reinterpret.Memory <ResourceBlock.Resource>(reader.ReadBytes(Marshal.SizeOf(typeof(ResourceBlock.Resource)))));
                    }
                }
            }
            #endregion
        }
示例#4
0
        public void WriteToDataStream(BinaryWriter writer)
        {
            int currentEnd = (int)writer.BaseStream.Position + MetaRootSize;

            int importNameBlockSize = 0;

            for (int i = 0; i < importNames.Count; i++)
            {
                importNameBlockSize += importNames[i].Length;
            }

            // tier 0
            writer.Write(playbackParameters.Count);
            writer.Write(currentEnd);
            currentEnd += playbackParameters.Count * Marshal.SizeOf(typeof(Playback));

            writer.Write(scales.Count);
            writer.Write(currentEnd);
            currentEnd += scales.Count * Marshal.SizeOf(typeof(Scale));

            writer.Write(importNames.Count);
            writer.Write(currentEnd);
            currentEnd += importNames.Count * sizeof(byte) + importNameBlockSize;

            writer.Write(pitchRangeParameters.Count);
            writer.Write(currentEnd);
            currentEnd += pitchRangeParameters.Count * Marshal.SizeOf(typeof(PitchRangeParametersBlock));

            writer.Write(pitchRanges.Count);
            writer.Write(currentEnd);
            currentEnd += pitchRanges.Count * Marshal.SizeOf(typeof(PitchRange));

            writer.Write(permutations.Count);
            writer.Write(currentEnd);
            currentEnd += permutations.Count * Marshal.SizeOf(typeof(Permutation));

            writer.Write(customPlaybacks.Count);
            writer.Write(currentEnd);
            currentEnd += customPlaybacks.Count * Marshal.SizeOf(typeof(CustomPlayback));

            writer.Write(runtimeFlags.Count);
            writer.Write(currentEnd);
            currentEnd += runtimeFlags.Count * Marshal.SizeOf(typeof(RuntimePermutationFlags));

            writer.Write(chunks.Count);
            writer.Write(currentEnd);
            currentEnd += chunks.Count * Marshal.SizeOf(typeof(Chunk));

            writer.Write(promotions.Count);
            writer.Write(currentEnd);
            currentEnd += promotions.Count * Marshal.SizeOf(typeof(Promotion));

            writer.Write(extraInfos.Count);
            writer.Write(currentEnd);
            currentEnd += extraInfos.Count * Marshal.SizeOf(typeof(ExtraInfo));

            // tier 1
            for (int i = 0; i < playbackParameters.Count; i++)
            {
                writer.Write(Reinterpret.Object <Playback>(playbackParameters[i]));
            }

            for (int i = 0; i < scales.Count; i++)
            {
                writer.Write(Reinterpret.Object <Scale>(scales[i]));
            }

            for (int i = 0; i < importNames.Count; i++)
            {
                writer.Write((byte)Encoding.ASCII.GetByteCount(importNames[i]));
                writer.Write(Encoding.ASCII.GetBytes(importNames[i]));
            }

            for (int i = 0; i < pitchRangeParameters.Count; i++)
            {
                writer.Write(Reinterpret.Object <PitchRangeParametersBlock>(pitchRangeParameters[i]));
            }

            for (int i = 0; i < pitchRanges.Count; i++)
            {
                writer.Write(Reinterpret.Object <PitchRange>(pitchRanges[i]));
            }

            for (int i = 0; i < permutations.Count; i++)
            {
                writer.Write(Reinterpret.Object <Permutation>(permutations[i]));
            }

            for (int i = 0; i < customPlaybacks.Count; i++)
            {
                CustomPlayback customPlayback = customPlaybacks[i];

                if (customPlayback.FilterCount > 0)
                {
                    customPlayback.FilterOffset = currentEnd;
                    currentEnd += customPlayback.FilterCount * Marshal.SizeOf(typeof(CustomPlayback.Filter));
                }
                else
                {
                    customPlayback.FilterOffset = 0;
                }

                if (customPlayback.PitchPlaybackParametersCount > 0)
                {
                    customPlayback.PitchPlaybackParametersOffset = currentEnd;
                    currentEnd += customPlayback.PitchPlaybackParametersCount * Marshal.SizeOf(typeof(CustomPlayback.PitchPlaybackParameters));
                }
                else
                {
                    customPlayback.PitchPlaybackParametersOffset = 0;
                }

                writer.Write(Reinterpret.Object <CustomPlayback>(customPlayback));
            }

            for (int i = 0; i < runtimeFlags.Count; i++)
            {
                writer.Write(Reinterpret.Object <RuntimePermutationFlags>(runtimeFlags[i]));
            }

            for (int i = 0; i < chunks.Count; i++)
            {
                writer.Write(Reinterpret.Object <Chunk>(chunks[i]));
            }

            for (int i = 0; i < promotions.Count; i++)
            {
                Promotion promotion = promotions[i];

                if (promotion.RuleCount > 0)
                {
                    promotion.RuleOffset = currentEnd;
                    currentEnd          += promotion.RuleCount * Marshal.SizeOf(typeof(Promotion.Rule));
                }
                else
                {
                    promotion.RuleOffset = 0;
                }

                if (promotion.TimerCount > 0)
                {
                    promotion.TimerOffset = currentEnd;
                    currentEnd           += promotion.TimerCount * Marshal.SizeOf(typeof(Promotion.Timer));
                }
                else
                {
                    promotion.TimerOffset = 0;
                }

                writer.Write(Reinterpret.Object <Promotion>(promotion));
            }

            for (int i = 0; i < extraInfos.Count; i++)
            {
                ExtraInfo extraInfo = extraInfos[i];

                if (extraInfo.ResourceBlock.RawSize > 0)
                {
                    uint encoded = Conversion.ToUInt(currentEnd) & 0x3fffffff;
                    encoded |= Conversion.ToUInt(extraInfo.ResourceBlock.RawOffset) & 0xc0000000;
                    extraInfo.ResourceBlock.RawOffset = Conversion.ToInt(encoded);
                    currentEnd += extraInfo.ResourceBlock.RawSize * sizeof(byte);
                }
                else
                {
                    extraInfo.ResourceBlock.RawOffset = 0;
                }

                if (extraInfo.ResourceBlock.ResourceCount > 0)
                {
                    extraInfo.ResourceBlock.ResourceOffset = currentEnd;
                    currentEnd += extraInfo.ResourceBlock.ResourceCount * Marshal.SizeOf(typeof(ResourceBlock.Resource));
                }
                else
                {
                    extraInfo.ResourceBlock.ResourceOffset = 0;
                }

                writer.Write(Reinterpret.Object <ExtraInfo>(extraInfo));
            }

            // tier 2
            for (int i = 0; i < customPlaybacks.Count; i++)
            {
                for (int j = 0; j < customPlaybacks[i].FilterCount; j++)
                {
                    writer.Write(Reinterpret.Object <CustomPlayback.Filter>(customFilters[i][j]));
                }
                for (int j = 0; j < customPlaybacks[i].PitchPlaybackParametersCount; j++)
                {
                    writer.Write(Reinterpret.Object <CustomPlayback.PitchPlaybackParameters>(customPitchParameters[i][j]));
                }
            }

            for (int i = 0; i < promotions.Count; i++)
            {
                for (int j = 0; j < promotions[i].RuleCount; j++)
                {
                    writer.Write(Reinterpret.Object <Promotion.Rule>(promotionRules[i][j]));
                }
                for (int j = 0; j < promotions[i].TimerCount; j++)
                {
                    writer.Write(Reinterpret.Object <Promotion.Timer>(promotionTimers[i][j]));
                }
            }

            for (int i = 0; i < extraInfos.Count; i++)
            {
                for (int j = 0; j < extraInfos[i].ResourceBlock.RawSize; j++)
                {
                    writer.Write(extraInfoData[i][j]);
                }
                for (int j = 0; j < extraInfos[i].ResourceBlock.ResourceCount; j++)
                {
                    writer.Write(Reinterpret.Object <ResourceBlock.Resource>(extraInfoResources[i][j]));
                }
            }
        }