Пример #1
0
		private static void ReadBlocks(IReader reader, ContainerReader containerFile, TagContainer tags)
		{
			while (containerFile.NextBlock())
			{
				switch (containerFile.BlockName)
				{
					case "data":
						// Data block
						tags.AddDataBlock(ReadDataBlock(reader, containerFile.BlockVersion));
						break;

					case "tag!":
						// Extracted tag
						tags.AddTag(ReadTag(reader, containerFile.BlockVersion));
						break;

					case "ersp":
						// Extracted Raw Resource Page
						tags.AddExtractedResourcePage(ReadExtractedResourcePage(reader, containerFile.BlockVersion));
						break;

					case "rspg":
						// Resource page
						tags.AddResourcePage(ReadResourcePage(reader, containerFile.BlockVersion));
						break;

					case "rsrc":
						// Resource info
						tags.AddResource(ReadResource(reader, containerFile.BlockVersion));
						break;
				}
			}
		}
Пример #2
0
        private static void WriteResourcePages(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (ResourcePage page in tags.ResourcePages)
            {
                container.StartBlock("rspg", 1);

                writer.WriteInt32(page.Index);
                writer.WriteUInt16(page.Salt);
                writer.WriteByte(page.Flags);
                writer.WriteAscii(page.FilePath ?? "");
                writer.WriteInt32(page.Offset);
                writer.WriteInt32(page.UncompressedSize);
                writer.WriteByte((byte) page.CompressionMethod);
                writer.WriteInt32(page.CompressedSize);
                writer.WriteUInt32(page.Checksum);
                WriteByteArray(page.Hash1, writer);
                WriteByteArray(page.Hash2, writer);
                WriteByteArray(page.Hash3, writer);
                writer.WriteInt32(page.Unknown1);
                writer.WriteInt32(page.Unknown2);
                writer.WriteInt32(page.Unknown3);

                container.EndBlock();
            }
        }
Пример #3
0
        public static void WriteTagContainer(TagContainer tags, IWriter writer)
        {
            var container = new ContainerWriter(writer);
            container.StartBlock("tagc", 0);

            WriteDataBlocks(tags, container, writer);
            WriteTags(tags, container, writer);
            WriteResourcePages(tags, container, writer);
            WriteResources(tags, container, writer);

            container.EndBlock();
        }
Пример #4
0
		public static TagContainer ReadTagContainer(IReader reader)
		{
			var tags = new TagContainer();

			var containerFile = new ContainerReader(reader);
			if (!containerFile.NextBlock() || containerFile.BlockName != "tagc")
				throw new ArgumentException("Not a valid tag container file");

			containerFile.EnterBlock();
			ReadBlocks(reader, containerFile, tags);
			containerFile.LeaveBlock();

			return tags;
		}
Пример #5
0
        private static void WriteDataBlocks(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (DataBlock dataBlock in tags.DataBlocks)
            {
                container.StartBlock("data", 2);

                // Main data
                writer.WriteUInt32(dataBlock.OriginalAddress);
                writer.WriteInt32(dataBlock.EntryCount);
                WriteByteArray(dataBlock.Data, writer);

                // Address fixups
                writer.WriteInt32(dataBlock.AddressFixups.Count);
                foreach (DataBlockAddressFixup blockRef in dataBlock.AddressFixups)
                {
                    writer.WriteUInt32(blockRef.OriginalAddress);
                    writer.WriteInt32(blockRef.WriteOffset);
                }

                // Tagref fixups
                writer.WriteInt32(dataBlock.TagFixups.Count);
                foreach (DataBlockTagFixup tagRef in dataBlock.TagFixups)
                {
                    writer.WriteUInt32(tagRef.OriginalIndex.Value);
                    writer.WriteInt32(tagRef.WriteOffset);
                }

                // Resource reference fixups
                writer.WriteInt32(dataBlock.ResourceFixups.Count);
                foreach (DataBlockResourceFixup resourceRef in dataBlock.ResourceFixups)
                {
                    writer.WriteUInt32(resourceRef.OriginalIndex.Value);
                    writer.WriteInt32(resourceRef.WriteOffset);
                }

                // StringID fixups
                writer.WriteInt32(dataBlock.StringIDFixups.Count);
                foreach (DataBlockStringIDFixup sid in dataBlock.StringIDFixups)
                {
                    writer.WriteAscii(sid.OriginalString);
                    writer.WriteInt32(sid.WriteOffset);
                }

                container.EndBlock();
            }
        }
Пример #6
0
 public TagContainerInjector(ICacheFile cacheFile, TagContainer container)
 {
     _cacheFile = cacheFile;
     _container = container;
 }
Пример #7
0
        private static void WriteResources(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (ExtractedResourceInfo resource in tags.Resources)
            {
                container.StartBlock("rsrc", 1);

                writer.WriteUInt32(resource.OriginalIndex.Value);
                writer.WriteUInt32(resource.Flags);
                if (resource.Type != null)
                    writer.WriteAscii(resource.Type);
                else
                    writer.WriteByte(0);
                WriteByteArray(resource.Info, writer);
                writer.WriteUInt32(resource.OriginalParentTagIndex.Value);
                if (resource.Location != null)
                {
                    writer.WriteByte(1);
                    writer.WriteInt32(resource.Location.OriginalPrimaryPageIndex);
                    writer.WriteInt32(resource.Location.PrimaryOffset);
                    writer.WriteInt32(resource.Location.PrimaryUnknown);
                    writer.WriteInt32(resource.Location.OriginalSecondaryPageIndex);
                    writer.WriteInt32(resource.Location.SecondaryOffset);
                    writer.WriteInt32(resource.Location.SecondaryUnknown);
                }
                else
                {
                    writer.WriteByte(0);
                }
                writer.WriteInt32(resource.Unknown1);
                writer.WriteInt32(resource.Unknown2);
                writer.WriteInt32(resource.Unknown3);

                writer.WriteInt32(resource.ResourceFixups.Count);
                foreach (ResourceFixup fixup in resource.ResourceFixups)
                {
                    writer.WriteInt32(fixup.Offset);
                    writer.WriteUInt32(fixup.Address);
                }

                writer.WriteInt32(resource.DefinitionFixups.Count);
                foreach (ResourceDefinitionFixup fixup in resource.DefinitionFixups)
                {
                    writer.WriteInt32(fixup.Offset);
                    writer.WriteInt32(fixup.Type);
                }

                container.EndBlock();
            }
        }
Пример #8
0
        private static void WriteTags(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (ExtractedTag tag in tags.Tags)
            {
                container.StartBlock("tag!", 0);

                writer.WriteUInt32(tag.OriginalIndex.Value);
                writer.WriteUInt32(tag.OriginalAddress);
                writer.WriteInt32(tag.Class);
                writer.WriteAscii(tag.Name);

                container.EndBlock();
            }
        }
Пример #9
0
        private void contextExtract_Click(object sender, RoutedEventArgs e)
        {
            // Get the menu item and the tag
            var item = e.Source as MenuItem;
            if (item == null)
                return;

            var tag = item.DataContext as TagEntry;
            if (tag == null)
                return;

            // Ask where to save the extracted tag collection
            var sfd = new SaveFileDialog
            {
                Title = "Save Tag Set",
                Filter = "Tag Container Files|*.tagc"
            };
            bool? result = sfd.ShowDialog();
            if (!result.Value)
                return;

            // Make a tag container
            var container = new TagContainer();

            // Recursively extract tags
            var tagsToProcess = new Queue<ITag>();
            var tagsProcessed = new HashSet<ITag>();
            var resourcesToProcess = new Queue<DatumIndex>();
            var resourcesProcessed = new HashSet<DatumIndex>();
            var resourcePagesProcessed = new HashSet<ResourcePage>();
            tagsToProcess.Enqueue(tag.RawTag);

            ResourceTable resources = null;
            using (IReader reader = _mapManager.OpenRead())
            {
                while (tagsToProcess.Count > 0)
                {
                    ITag currentTag = tagsToProcess.Dequeue();
                    if (tagsProcessed.Contains(currentTag))
                        continue;

                    // Get the plugin path
                    string className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(currentTag.Class.Magic)).Trim();
                    string pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins",
                        _buildInfo.Settings.GetSetting<string>("plugins"), className);

                    // Extract dem data blocks
                    var blockBuilder = new DataBlockBuilder(reader, currentTag.MetaLocation, _cacheFile, _buildInfo);
                    using (XmlReader pluginReader = XmlReader.Create(pluginPath))
                        AssemblyPluginLoader.LoadPlugin(pluginReader, blockBuilder);

                    foreach (DataBlock block in blockBuilder.DataBlocks)
                        container.AddDataBlock(block);

                    // Add data for the tag that was extracted
                    string tagName = _cacheFile.FileNames.GetTagName(currentTag) ?? currentTag.Index.ToString();
                    var extractedTag = new ExtractedTag(currentTag.Index, currentTag.MetaLocation.AsPointer(), currentTag.Class.Magic,
                        tagName);
                    container.AddTag(extractedTag);

                    // Mark the tag as processed and then enqueue all of its child tags and resources
                    tagsProcessed.Add(currentTag);
                    foreach (DatumIndex tagRef in blockBuilder.ReferencedTags)
                        tagsToProcess.Enqueue(_cacheFile.Tags[tagRef]);
                    foreach (DatumIndex resource in blockBuilder.ReferencedResources)
                        resourcesToProcess.Enqueue(resource);
                }

                // Load the resource table in if necessary
                if (resourcesToProcess.Count > 0)
                    resources = _cacheFile.Resources.LoadResourceTable(reader);
            }

            // Extract resource info
            if (resources != null)
            {
                while (resourcesToProcess.Count > 0)
                {
                    DatumIndex index = resourcesToProcess.Dequeue();
                    if (resourcesProcessed.Contains(index))
                        continue;

                    // Add the resource
                    Resource resource = resources.Resources[index.Index];
                    container.AddResource(new ExtractedResourceInfo(resource));

                    // Add data for its pages
                    if (resource.Location == null)
                        continue;
                    if (resource.Location.PrimaryPage != null && !resourcePagesProcessed.Contains(resource.Location.PrimaryPage))
                    {
                        container.AddResourcePage(resource.Location.PrimaryPage);
                        resourcePagesProcessed.Add(resource.Location.PrimaryPage);
                    }
                    if (resource.Location.SecondaryPage == null || resourcePagesProcessed.Contains(resource.Location.SecondaryPage))
                        continue;
                    container.AddResourcePage(resource.Location.SecondaryPage);
                    resourcePagesProcessed.Add(resource.Location.SecondaryPage);
                }
            }

            // Write it to a file
            using (var writer = new EndianWriter(File.Open(sfd.FileName, FileMode.Create, FileAccess.Write), Endian.BigEndian))
                TagContainerWriter.WriteTagContainer(container, writer);

            // YAY!
            MetroMessageBox.Show("Extraction Successful",
                "Extracted " + container.Tags.Count + " tag(s), " + container.DataBlocks.Count + " data block(s), " +
                container.ResourcePages.Count + " resource page pointer(s), and " + container.Resources.Count +
                " resource pointer(s).");
        }
Пример #10
0
		public TagContainerInjector(ICacheFile cacheFile, TagContainer container)
		{
			_cacheFile = cacheFile;
			_languageCache = new CachedLanguagePackLoader(cacheFile.Languages);
			_container = container;
		}
Пример #11
0
        private static void WriteSoundExtraInfos(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (var extra in tags.SoundExtraInfos)
            {
                container.StartBlock("snex", 0);

                writer.WriteInt32(extra.OriginalIndex);

                if (extra.Source.PermutationSections != null)
                {
                    writer.WriteInt32(extra.Source.PermutationSections.Length);
                    foreach (var psection in extra.Source.PermutationSections)
                    {
                        writer.WriteInt32(psection.EncodedData.Length);
                        writer.WriteBlock(psection.EncodedData);

                        if (psection.DialogueInfos != null)
                        {
                            writer.WriteInt32(psection.DialogueInfos.Length);
                            foreach (var dialogue in psection.DialogueInfos)
                            {
                                writer.WriteInt32(dialogue.MouthOffset);
                                writer.WriteInt32(dialogue.MouthLength);
                                writer.WriteInt32(dialogue.LipsyncOffset);
                                writer.WriteInt32(dialogue.LipsyncLength);
                            }
                        }
                        else
                        {
                            writer.WriteInt32(0);
                        }

                        if (psection.Unknown1s != null)
                        {
                            writer.WriteInt32(psection.Unknown1s.Length);
                            foreach (var unk1 in psection.Unknown1s)
                            {
                                writer.WriteInt32(unk1.Unknown);
                                writer.WriteInt32(unk1.Unknown1);
                                writer.WriteInt32(unk1.Unknown2);
                                writer.WriteInt32(unk1.Unknown3);
                                writer.WriteInt32(unk1.Unknown4);
                                writer.WriteInt32(unk1.Unknown5);
                                writer.WriteInt32(unk1.Unknown6);
                                writer.WriteInt32(unk1.Unknown7);
                                writer.WriteInt32(unk1.Unknown8);
                                writer.WriteInt32(unk1.Unknown9);
                                writer.WriteInt32(unk1.Unknown10);
                                writer.WriteInt32(unk1.Unknown11);

                                if (unk1.Unknown12s != null)
                                {
                                    writer.WriteInt32(unk1.Unknown12s.Length);
                                    foreach (var unk2 in unk1.Unknown12s)
                                    {
                                        writer.WriteFloat(unk2.Unknown);
                                        writer.WriteFloat(unk2.Unknown1);
                                        writer.WriteFloat(unk2.Unknown2);
                                        writer.WriteFloat(unk2.Unknown3);

                                        if (unk2.Unknown5s != null)
                                        {
                                            writer.WriteInt32(unk2.Unknown5s.Length);
                                            foreach (var unk3 in unk2.Unknown5s)
                                            {
                                                writer.WriteInt32(unk3.Unknown);
                                                writer.WriteInt32(unk3.Unknown1);
                                                writer.WriteInt32(unk3.Unknown2);
                                                writer.WriteInt32(unk3.Unknown3);
                                            }
                                        }
                                        else
                                        {
                                            writer.WriteInt32(0);
                                        }

                                        if (unk2.Unknown6s != null)
                                        {
                                            writer.WriteInt32(unk2.Unknown6s.Length);
                                            foreach (var unk4 in unk2.Unknown6s)
                                            {
                                                writer.WriteInt32(unk4.Unknown);
                                                writer.WriteInt32(unk4.Unknown1);
                                            }
                                        }
                                        else
                                        {
                                            writer.WriteInt32(0);
                                        }
                                    }
                                }
                                else
                                {
                                    writer.WriteInt32(0);
                                }
                            }
                        }
                        else
                        {
                            writer.WriteInt32(0);
                        }
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                if (extra.Source.Datums != null)
                {
                    writer.WriteInt32(extra.Source.Datums.Length);
                    foreach (var d in extra.Source.Datums)
                    {
                        writer.WriteUInt32(d.Value);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                container.EndBlock();
            }
        }
Пример #12
0
        private static void WriteSoundCustomPlaybacks(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (var cplayback in tags.SoundCustomPlaybacks)
            {
                container.StartBlock("scpb", 0);

                writer.WriteInt32(cplayback.OriginalIndex);

                writer.WriteByte((byte)cplayback.Version);

                writer.WriteInt32(cplayback.Flags);

                writer.WriteInt32(cplayback.Unknown);
                writer.WriteInt32(cplayback.Unknown1);

                //theres a final block that goes here

                if (cplayback.Mixes != null)
                {
                    writer.WriteInt32(cplayback.Mixes.Count);
                    foreach (var mix in cplayback.Mixes)
                    {
                        writer.WriteInt32(mix.Mixbin);
                        writer.WriteFloat(mix.Gain);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                if (cplayback.Filters != null)
                {
                    writer.WriteInt32(cplayback.Filters.Count);
                    foreach (var filter in cplayback.Filters)
                    {
                        writer.WriteInt32(filter.Type);
                        writer.WriteInt32(filter.Width);

                        writer.WriteFloat(filter.LeftFreqScaleMin);
                        writer.WriteFloat(filter.LeftFreqScaleMax);
                        writer.WriteFloat(filter.LeftFreqRandomBase);
                        writer.WriteFloat(filter.LeftFreqRandomVariance);

                        writer.WriteFloat(filter.LeftGainScaleMin);
                        writer.WriteFloat(filter.LeftGainScaleMax);
                        writer.WriteFloat(filter.LeftGainRandomBase);
                        writer.WriteFloat(filter.LeftGainRandomVariance);

                        writer.WriteFloat(filter.RightFreqScaleMin);
                        writer.WriteFloat(filter.RightFreqScaleMax);
                        writer.WriteFloat(filter.RightFreqRandomBase);
                        writer.WriteFloat(filter.RightFreqRandomVariance);

                        writer.WriteFloat(filter.RightGainScaleMin);
                        writer.WriteFloat(filter.RightGainScaleMax);
                        writer.WriteFloat(filter.RightGainRandomBase);
                        writer.WriteFloat(filter.RightGainRandomVariance);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                if (cplayback.PitchLFOs != null)
                {
                    writer.WriteInt32(cplayback.PitchLFOs.Count);
                    foreach (var pitchlfo in cplayback.PitchLFOs)
                    {
                        writer.WriteFloat(pitchlfo.DelayScaleMin);
                        writer.WriteFloat(pitchlfo.DelayScaleMax);
                        writer.WriteFloat(pitchlfo.DelayRandomBase);
                        writer.WriteFloat(pitchlfo.DelayRandomVariance);

                        writer.WriteFloat(pitchlfo.FreqScaleMin);
                        writer.WriteFloat(pitchlfo.FreqScaleMax);
                        writer.WriteFloat(pitchlfo.FreqRandomBase);
                        writer.WriteFloat(pitchlfo.FreqRandomVariance);

                        writer.WriteFloat(pitchlfo.PitchModScaleMin);
                        writer.WriteFloat(pitchlfo.PitchModScaleMax);
                        writer.WriteFloat(pitchlfo.PitchModRandomBase);
                        writer.WriteFloat(pitchlfo.PitchModRandomVariance);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                if (cplayback.FilterLFOs != null)
                {
                    writer.WriteInt32(cplayback.FilterLFOs.Count);
                    foreach (var filterlfo in cplayback.FilterLFOs)
                    {
                        writer.WriteFloat(filterlfo.DelayScaleMin);
                        writer.WriteFloat(filterlfo.DelayScaleMax);
                        writer.WriteFloat(filterlfo.DelayRandomBase);
                        writer.WriteFloat(filterlfo.DelayRandomVariance);

                        writer.WriteFloat(filterlfo.FreqScaleMin);
                        writer.WriteFloat(filterlfo.FreqScaleMax);
                        writer.WriteFloat(filterlfo.FreqRandomBase);
                        writer.WriteFloat(filterlfo.FreqRandomVariance);

                        writer.WriteFloat(filterlfo.CutoffModScaleMin);
                        writer.WriteFloat(filterlfo.CutoffModScaleMax);
                        writer.WriteFloat(filterlfo.CutoffModRandomBase);
                        writer.WriteFloat(filterlfo.CutoffModRandomVariance);

                        writer.WriteFloat(filterlfo.GainModScaleMin);
                        writer.WriteFloat(filterlfo.GainModScaleMax);
                        writer.WriteFloat(filterlfo.GainModRandomBase);
                        writer.WriteFloat(filterlfo.GainModRandomVariance);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                writer.WriteUInt32(cplayback.OriginalRadioEffect.Value);

                if (cplayback.LowpassEffects != null)
                {
                    writer.WriteInt32(cplayback.LowpassEffects.Count);
                    foreach (var lowpass in cplayback.LowpassEffects)
                    {
                        writer.WriteFloat(lowpass.Attack);
                        writer.WriteFloat(lowpass.Release);
                        writer.WriteFloat(lowpass.CutoffFrequency);
                        writer.WriteFloat(lowpass.OutputGain);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                if (cplayback.Components != null)
                {
                    writer.WriteInt32(cplayback.Components.Count);
                    foreach (var comp in cplayback.Components)
                    {
                        writer.WriteUInt32(comp.OriginalSound.Value);
                        writer.WriteFloat(comp.Gain);
                        writer.WriteInt32(comp.Flags);
                    }
                }
                else
                {
                    writer.WriteInt32(0);
                }

                container.EndBlock();
            }
        }
Пример #13
0
        private static void WriteSoundPitchRanges(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (var pRange in tags.SoundPitchRanges)
            {
                container.StartBlock("snpr", 1);

                writer.WriteInt32(pRange.OriginalIndex);

                writer.WriteAscii(pRange.Name);

                if (pRange.Parameter != null)
                {
                    writer.WriteByte(1);
                    writer.WriteInt32(pRange.Parameter.NaturalPitch);
                    writer.WriteInt32(pRange.Parameter.BendMin);
                    writer.WriteInt32(pRange.Parameter.BendMax);
                    writer.WriteInt32(pRange.Parameter.MaxGainPitchMin);
                    writer.WriteInt32(pRange.Parameter.MaxGainPitchMax);
                    writer.WriteInt32(pRange.Parameter.PlaybackPitchMin);
                    writer.WriteInt32(pRange.Parameter.PlaybackPitchMax);

                    if (pRange.Parameter.Distance != null)
                    {
                        writer.WriteByte(1);
                        writer.WriteFloat(pRange.Parameter.Distance.DontPlayDistance);
                        writer.WriteFloat(pRange.Parameter.Distance.AttackDistance);
                        writer.WriteFloat(pRange.Parameter.Distance.MinDistance);
                        writer.WriteFloat(pRange.Parameter.Distance.MaxDistance);
                    }
                    else
                    {
                        writer.WriteByte(0);
                    }
                }
                else
                {
                    writer.WriteByte(0);
                }

                writer.WriteByte(pRange.HasEncodedData ? (byte)1 : (byte)0);

                writer.WriteInt32(pRange.RequiredPermutationCount);

                writer.WriteInt32(pRange.Permutations.Count);
                foreach (var perm in pRange.Permutations)
                {
                    writer.WriteAscii(perm.Name);

                    writer.WriteInt32(perm.EncodedSkipFraction);
                    writer.WriteInt32(perm.SampleSize);
                    writer.WriteInt32(perm.EncodedGain);
                    writer.WriteInt32(perm.EncodedPermutationInfoIndex);
                    writer.WriteInt32(perm.FSBInfo);

                    if (perm.Chunks != null)
                    {
                        writer.WriteInt32(perm.Chunks.Count);
                        foreach (var chunk in perm.Chunks)
                        {
                            writer.WriteInt32(chunk.Source.FileOffset);
                            writer.WriteInt32(chunk.Source.EncodedSizeAndFlags);
                            writer.WriteInt32(chunk.Source.CacheIndex);
                            writer.WriteInt32(chunk.Source.XMA2BufferStart);
                            writer.WriteInt32(chunk.Source.XMA2BufferEnd);
                            writer.WriteInt32(chunk.Source.Unknown);
                            writer.WriteInt32(chunk.Source.Unknown1);
                            writer.WriteAscii(chunk.FModBankSuffix);
                        }
                    }
                    else
                    {
                        writer.WriteInt32(0);
                    }

                    if (perm.Languages != null)
                    {
                        writer.WriteInt32(perm.Languages.Count);
                        foreach (var lang in perm.Languages)
                        {
                            writer.WriteInt32(lang.LanguageIndex);
                            writer.WriteInt32(lang.SampleSize);

                            if (lang.Chunks != null)
                            {
                                writer.WriteInt32(lang.Chunks.Count);
                                foreach (var chunk in lang.Chunks)
                                {
                                    writer.WriteInt32(chunk.Source.FileOffset);
                                    writer.WriteInt32(chunk.Source.EncodedSizeAndFlags);
                                    writer.WriteInt32(chunk.Source.CacheIndex);
                                    writer.WriteInt32(chunk.Source.XMA2BufferStart);
                                    writer.WriteInt32(chunk.Source.XMA2BufferEnd);
                                    writer.WriteInt32(chunk.Source.Unknown);
                                    writer.WriteInt32(chunk.Source.Unknown1);
                                    writer.WriteAscii(chunk.FModBankSuffix);
                                }
                            }
                            else
                            {
                                writer.WriteInt32(0);
                            }
                        }
                    }
                    else
                    {
                        writer.WriteInt32(0);
                    }

                    if (perm.LayerMarkers != null)
                    {
                        writer.WriteInt32(perm.LayerMarkers.Count);
                        foreach (var marker in perm.LayerMarkers)
                        {
                            writer.WriteInt32(marker);
                        }
                    }
                    else
                    {
                        writer.WriteInt32(0);
                    }
                }

                container.EndBlock();
            }
        }
Пример #14
0
        private void extractTags(bool withRaw, TagEntry tag)
        {
            // Ask where to save the extracted tag collection
            var sfd = new SaveFileDialog
            {
                Title = "Save Tag Set",
                Filter = "Tag Container Files|*.tagc"
            };
            bool? result = sfd.ShowDialog();
            if (!result.Value)
                return;

            // Make a tag container
            var container = new TagContainer();

            // Recursively extract tags
            var tagsToProcess = new Queue<ITag>();
            var tagsProcessed = new HashSet<ITag>();
            var resourcesToProcess = new Queue<DatumIndex>();
            var resourcesProcessed = new HashSet<DatumIndex>();
            var resourcePagesProcessed = new HashSet<ResourcePage>();
            tagsToProcess.Enqueue(tag.RawTag);

            ResourceTable resources = null;
            using (var reader = _mapManager.OpenRead())
            {
                while (tagsToProcess.Count > 0)
                {
                    var currentTag = tagsToProcess.Dequeue();
                    if (tagsProcessed.Contains(currentTag))
                        continue;

                    // Get the plugin path
                    var className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(currentTag.Class.Magic)).Trim();
                    var pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins",
                        _buildInfo.Settings.GetSetting<string>("plugins"), className);

                    // Extract dem data blocks
                    var blockBuilder = new DataBlockBuilder(reader, currentTag, _cacheFile, _buildInfo);
                    using (var pluginReader = XmlReader.Create(pluginPath))
                        AssemblyPluginLoader.LoadPlugin(pluginReader, blockBuilder);

                    foreach (var block in blockBuilder.DataBlocks)
                        container.AddDataBlock(block);

                    // Add data for the tag that was extracted
                    var tagName = _cacheFile.FileNames.GetTagName(currentTag) ?? currentTag.Index.ToString();
                    var extractedTag = new ExtractedTag(currentTag.Index, currentTag.MetaLocation.AsPointer(), currentTag.Class.Magic,
                        tagName);
                    container.AddTag(extractedTag);

                    // Mark the tag as processed and then enqueue all of its child tags and resources
                    tagsProcessed.Add(currentTag);
                    foreach (var tagRef in blockBuilder.ReferencedTags)
                        tagsToProcess.Enqueue(_cacheFile.Tags[tagRef]);
                    foreach (var resource in blockBuilder.ReferencedResources)
                        resourcesToProcess.Enqueue(resource);
                }

                // Load the resource table in if necessary
                if (resourcesToProcess.Count > 0)
                    resources = _cacheFile.Resources.LoadResourceTable(reader);
            }

            // Extract resource info
            if (resources != null)
            {
                while (resourcesToProcess.Count > 0)
                {
                    var index = resourcesToProcess.Dequeue();
                    if (resourcesProcessed.Contains(index))
                        continue;

                    // Add the resource
                    var resource = resources.Resources[index.Index];
                    container.AddResource(new ExtractedResourceInfo(index, resource));

                    // Add data for its pages
                    if (resource.Location == null) continue;

                    if (resource.Location.PrimaryPage != null &&
                        !resourcePagesProcessed.Contains(resource.Location.PrimaryPage))
                    {
                        container.AddResourcePage(resource.Location.PrimaryPage);
                        resourcePagesProcessed.Add(resource.Location.PrimaryPage);

                        if (withRaw)
                        {
                            using (var fileStream = File.OpenRead(_cacheLocation))
                            {
                                var resourceFile = _cacheFile;
                                Stream resourceStream = fileStream;
                                if (resource.Location.PrimaryPage.FilePath != null)
                                {
                                    var resourceCacheInfo =
                                    App.AssemblyStorage.AssemblySettings.HalomapResourceCachePaths.FirstOrDefault(
                                        r => r.EngineName == _buildInfo.Name);

                                    var resourceCachePath = (resourceCacheInfo != null)
                                        ? resourceCacheInfo.ResourceCachePath
                                        : Path.GetDirectoryName(_cacheLocation);

                                    resourceCachePath = Path.Combine(resourceCachePath ?? "", Path.GetFileName(resource.Location.PrimaryPage.FilePath));

                                    if (!File.Exists(resourceCachePath))
                                    {
                                        MetroMessageBox.Show("Unable to extract tag",
                                            "Unable to extract tag, because a resource it relies on is in a external cache '{0}' that could not be found. Check Assembly's settings and set the file path to resource caches.");
                                        return;
                                    }

                                    resourceStream =
                                        File.OpenRead(resourceCachePath);
                                    resourceFile = new ThirdGenCacheFile(new EndianReader(resourceStream, Endian.BigEndian), _buildInfo,
                                        _cacheFile.BuildString);
                                }

                                var extractor = new ResourcePageExtractor(resourceFile);
                                byte[] pageData;
                                using (var pageStream = new MemoryStream())
                                {
                                    extractor.ExtractPage(resource.Location.PrimaryPage, resourceStream, pageStream);
                                    pageData = new byte[pageStream.Length];
                                    Buffer.BlockCopy(pageStream.GetBuffer(), 0, pageData, 0, (int) pageStream.Length);
                                }
                                container.AddExtractedResourcePage(new ExtractedPage(pageData, resource.Location.PrimaryPage.Index));
                            }
                        }
                    }
                    if (resource.Location.SecondaryPage == null || resourcePagesProcessed.Contains(resource.Location.SecondaryPage))
                        continue;

                    container.AddResourcePage(resource.Location.SecondaryPage);
                    resourcePagesProcessed.Add(resource.Location.SecondaryPage);

                    if (withRaw)
                    {
                        using (var fileStream = File.OpenRead(_cacheLocation))
                        {
                            var resourceFile = _cacheFile;
                            Stream resourceStream = fileStream;
                            if (resource.Location.SecondaryPage.FilePath != null)
                            {
                                var resourceCacheInfo =
                                    App.AssemblyStorage.AssemblySettings.HalomapResourceCachePaths.FirstOrDefault(
                                        r => r.EngineName == _buildInfo.Name);

                                var resourceCachePath = (resourceCacheInfo != null)
                                    ? resourceCacheInfo.ResourceCachePath
                                    : Path.GetDirectoryName(_cacheLocation);

                                resourceCachePath = Path.Combine(resourceCachePath ?? "", Path.GetFileName(resource.Location.SecondaryPage.FilePath));

                                if (!File.Exists(resourceCachePath))
                                {
                                    MetroMessageBox.Show("Unable to extract tag",
                                        "Unable to extract tag, because a resource it relies on is in a external cache '{0}' that could not be found. Check Assembly's settings and set the file path to resource caches.");
                                    return;
                                }

                                resourceStream =
                                    File.OpenRead(resourceCachePath);
                                resourceFile = new ThirdGenCacheFile(new EndianReader(resourceStream, Endian.BigEndian), _buildInfo,
                                    _cacheFile.BuildString);
                            }

                            var extractor = new ResourcePageExtractor(resourceFile);
                            byte[] pageData;
                            using (var pageStream = new MemoryStream())
                            {
                                extractor.ExtractPage(resource.Location.SecondaryPage, resourceStream, pageStream);
                                pageData = new byte[pageStream.Length];
                                Buffer.BlockCopy(pageStream.GetBuffer(), 0, pageData, 0, (int)pageStream.Length);
                            }
                            container.AddExtractedResourcePage(new ExtractedPage(pageData, resource.Location.SecondaryPage.Index));
                        }
                    }
                }
            }

            // Write it to a file
            using (var writer = new EndianWriter(File.Open(sfd.FileName, FileMode.Create, FileAccess.Write), Endian.BigEndian))
                TagContainerWriter.WriteTagContainer(container, writer);

            // YAY!
            MetroMessageBox.Show("Extraction Successful",
                "Extracted " +
                container.Tags.Count + " tag(s), " +
                container.DataBlocks.Count + " data block(s), " +
                container.ResourcePages.Count + " resource page pointer(s), " +
                container.ExtractedResourcePages.Count + " extracted resource page(s), and " +
                container.Resources.Count + " resource pointer(s).");
        }
Пример #15
0
 public TagContainerInjector(ICacheFile cacheFile, TagContainer container)
 {
     _cacheFile     = cacheFile;
     _languageCache = new CachedLanguagePackLoader(cacheFile.Languages);
     _container     = container;
 }
Пример #16
0
		private static void WriteDataBlocks(TagContainer tags, ContainerWriter container, IWriter writer)
		{
			foreach (DataBlock dataBlock in tags.DataBlocks)
			{
				container.StartBlock("data", 6);

				// Main data
				writer.WriteUInt32(dataBlock.OriginalAddress);
				writer.WriteInt32(dataBlock.EntryCount);
				writer.WriteInt32(dataBlock.Alignment);
				WriteByteArray(dataBlock.Data, writer);

				// Address fixups
				writer.WriteInt32(dataBlock.AddressFixups.Count);
				foreach (DataBlockAddressFixup blockRef in dataBlock.AddressFixups)
				{
					writer.WriteUInt32(blockRef.OriginalAddress);
					writer.WriteInt32(blockRef.WriteOffset);
				}

				// Tagref fixups
				writer.WriteInt32(dataBlock.TagFixups.Count);
				foreach (DataBlockTagFixup tagRef in dataBlock.TagFixups)
				{
					writer.WriteUInt32(tagRef.OriginalIndex.Value);
					writer.WriteInt32(tagRef.WriteOffset);
				}

				// Resource reference fixups
				writer.WriteInt32(dataBlock.ResourceFixups.Count);
				foreach (DataBlockResourceFixup resourceRef in dataBlock.ResourceFixups)
				{
					writer.WriteUInt32(resourceRef.OriginalIndex.Value);
					writer.WriteInt32(resourceRef.WriteOffset);
				}

				// StringID fixups
				writer.WriteInt32(dataBlock.StringIDFixups.Count);
				foreach (DataBlockStringIDFixup sid in dataBlock.StringIDFixups)
				{
					writer.WriteAscii(sid.OriginalString);
					writer.WriteInt32(sid.WriteOffset);
				}

				// Shader fixups
				writer.WriteInt32(dataBlock.ShaderFixups.Count);
				foreach (DataBlockShaderFixup shaderRef in dataBlock.ShaderFixups)
				{
					writer.WriteInt32(shaderRef.WriteOffset);
					if (shaderRef.Data != null)
					{
						writer.WriteInt32(shaderRef.Data.Length);
						writer.WriteBlock(shaderRef.Data);
					}
					else
					{
						writer.WriteInt32(0);
					}
				}

				// Unicode string list fixups
				writer.WriteInt32(dataBlock.UnicListFixups.Count);
				foreach (DataBlockUnicListFixup unicList in dataBlock.UnicListFixups)
				{
					writer.WriteInt32(unicList.LanguageIndex);
					writer.WriteInt32(unicList.WriteOffset);
					writer.WriteInt32(unicList.Strings.Length);
					foreach (UnicListFixupString str in unicList.Strings)
					{
						writer.WriteAscii(str.StringID);
						writer.WriteUTF8(str.String);
					}
				}

				container.EndBlock();
			}
		}
Пример #17
0
		private static void WriteExtractedResourcePages(TagContainer tags, ContainerWriter container, IWriter writer)
		{
			foreach (var extractedPage in tags.ExtractedResourcePages)
			{
				container.StartBlock("ersp", 0);

				writer.WriteInt32(extractedPage.ResourcePageIndex);
				WriteByteArray(extractedPage.ExtractedPageData, writer);

				container.EndBlock();
			}
		}
Пример #18
0
        private static void WriteDataBlocks(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (DataBlock dataBlock in tags.DataBlocks)
            {
                container.StartBlock("data", 7);

                // Main data
                writer.WriteUInt32(dataBlock.OriginalAddress);
                writer.WriteInt32(dataBlock.EntryCount);
                writer.WriteInt32(dataBlock.Alignment);
                writer.WriteByte((byte)(dataBlock.Sortable == true ? 1 : 0));
                WriteByteArray(dataBlock.Data, writer);

                // Address fixups
                writer.WriteInt32(dataBlock.AddressFixups.Count);
                foreach (DataBlockAddressFixup blockRef in dataBlock.AddressFixups)
                {
                    writer.WriteUInt32(blockRef.OriginalAddress);
                    writer.WriteInt32(blockRef.WriteOffset);
                }

                // Tagref fixups
                writer.WriteInt32(dataBlock.TagFixups.Count);
                foreach (DataBlockTagFixup tagRef in dataBlock.TagFixups)
                {
                    writer.WriteUInt32(tagRef.OriginalIndex.Value);
                    writer.WriteInt32(tagRef.WriteOffset);
                }

                // Resource reference fixups
                writer.WriteInt32(dataBlock.ResourceFixups.Count);
                foreach (DataBlockResourceFixup resourceRef in dataBlock.ResourceFixups)
                {
                    writer.WriteUInt32(resourceRef.OriginalIndex.Value);
                    writer.WriteInt32(resourceRef.WriteOffset);
                }

                // StringID fixups
                writer.WriteInt32(dataBlock.StringIDFixups.Count);
                foreach (DataBlockStringIDFixup sid in dataBlock.StringIDFixups)
                {
                    writer.WriteAscii(sid.OriginalString);
                    writer.WriteInt32(sid.WriteOffset);
                }

                // Shader fixups
                writer.WriteInt32(dataBlock.ShaderFixups.Count);
                foreach (DataBlockShaderFixup shaderRef in dataBlock.ShaderFixups)
                {
                    writer.WriteInt32(shaderRef.WriteOffset);
                    if (shaderRef.Data != null)
                    {
                        writer.WriteInt32(shaderRef.Data.Length);
                        writer.WriteBlock(shaderRef.Data);
                    }
                    else
                    {
                        writer.WriteInt32(0);
                    }
                }

                // Unicode string list fixups
                writer.WriteInt32(dataBlock.UnicListFixups.Count);
                foreach (DataBlockUnicListFixup unicList in dataBlock.UnicListFixups)
                {
                    writer.WriteInt32(unicList.LanguageIndex);
                    writer.WriteInt32(unicList.WriteOffset);
                    writer.WriteInt32(unicList.Strings.Length);
                    foreach (UnicListFixupString str in unicList.Strings)
                    {
                        writer.WriteAscii(str.StringID);
                        writer.WriteUTF8(str.String);
                    }
                }

                // Model Data fixups
                writer.WriteInt32(dataBlock.InteropFixups.Count);
                foreach (DataBlockInteropFixup interop in dataBlock.InteropFixups)
                {
                    writer.WriteUInt32(interop.OriginalAddress);
                    writer.WriteInt32(interop.WriteOffset);
                    writer.WriteInt32(interop.Type);
                }

                // Effect fixups
                writer.WriteInt32(dataBlock.EffectFixups.Count);
                foreach (DataBlockEffectFixup effectData in dataBlock.EffectFixups)
                {
                    writer.WriteInt32(effectData.OriginalIndex);
                    writer.WriteInt32(effectData.WriteOffset);
                    writer.WriteInt32(effectData.Type);
                    if (effectData.Data != null)
                    {
                        writer.WriteInt32(effectData.Data.Length);
                        writer.WriteBlock(effectData.Data);
                    }
                    else
                    {
                        writer.WriteInt32(0);
                    }
                }

                container.EndBlock();
            }
        }
Пример #19
0
        private static void WriteResources(TagContainer tags, ContainerWriter container, IWriter writer)
        {
            foreach (ExtractedResourceInfo resource in tags.Resources)
            {
                container.StartBlock("rsrc", 2);

                writer.WriteUInt32(resource.OriginalIndex.Value);
                writer.WriteUInt32(resource.Flags);
                if (resource.Type != null)
                {
                    writer.WriteAscii(resource.Type);
                }
                else
                {
                    writer.WriteByte(0);
                }
                WriteByteArray(resource.Info, writer);

                writer.WriteUInt32(resource.OriginalParentTagIndex.Value);
                if (resource.Location != null)
                {
                    writer.WriteByte(1);
                    writer.WriteInt32(resource.Location.OriginalPrimaryPageIndex);
                    writer.WriteInt32(resource.Location.PrimaryOffset);
                    if (resource.Location.PrimarySize != null)
                    {
                        writer.WriteInt32(resource.Location.PrimarySize.Size);
                        writer.WriteByte((byte)resource.Location.PrimarySize.Parts.Count);
                        foreach (ResourceSizePart part in resource.Location.PrimarySize.Parts)
                        {
                            writer.WriteInt32(part.Offset);
                            writer.WriteInt32(part.Size);
                        }
                    }
                    else
                    {
                        writer.WriteInt32(-1);
                    }

                    writer.WriteInt32(resource.Location.OriginalSecondaryPageIndex);
                    writer.WriteInt32(resource.Location.SecondaryOffset);
                    if (resource.Location.SecondarySize != null)
                    {
                        writer.WriteInt32(resource.Location.SecondarySize.Size);
                        writer.WriteByte((byte)resource.Location.SecondarySize.Parts.Count);
                        foreach (ResourceSizePart part in resource.Location.SecondarySize.Parts)
                        {
                            writer.WriteInt32(part.Offset);
                            writer.WriteInt32(part.Size);
                        }
                    }
                    else
                    {
                        writer.WriteInt32(-1);
                    }

                    writer.WriteInt32(resource.Location.OriginalTertiaryPageIndex);
                    writer.WriteInt32(resource.Location.TertiaryOffset);
                    if (resource.Location.TertiarySize != null)
                    {
                        writer.WriteInt32(resource.Location.TertiarySize.Size);
                        writer.WriteByte((byte)resource.Location.TertiarySize.Parts.Count);
                        foreach (ResourceSizePart part in resource.Location.TertiarySize.Parts)
                        {
                            writer.WriteInt32(part.Offset);
                            writer.WriteInt32(part.Size);
                        }
                    }
                    else
                    {
                        writer.WriteInt32(-1);
                    }
                }
                else
                {
                    writer.WriteByte(0);
                }

                writer.WriteInt32(resource.ResourceBits);
                writer.WriteInt32(resource.BaseDefinitionAddress);

                writer.WriteInt32(resource.ResourceFixups.Count);
                foreach (ResourceFixup fixup in resource.ResourceFixups)
                {
                    writer.WriteInt32(fixup.Offset);
                    writer.WriteUInt32(fixup.Address);
                }

                writer.WriteInt32(resource.DefinitionFixups.Count);
                foreach (ResourceDefinitionFixup fixup in resource.DefinitionFixups)
                {
                    writer.WriteInt32(fixup.Offset);
                    writer.WriteInt32(fixup.Type);
                }

                container.EndBlock();
            }
        }
Пример #20
0
        private void contextDuplicate_Click(object sender, RoutedEventArgs e)
        {
            // Get the menu item and the tag
            var item = e.Source as MenuItem;
            if (item == null)
                return;
            var tag = item.DataContext as TagEntry;
            if (tag == null)
                return;

            // TODO: Make this into a dialog with more options
            string newName;
            while (true)
            {
                newName = MetroInputBox.Show("Duplicate Tag", "Please enter a name for the new tag.", tag.TagFileName, "Enter a name.");
                if (newName == null)
                    return;
                if (newName != tag.TagFileName && _cacheFile.Tags.FindTagByName(newName, tag.RawTag.Class, _cacheFile.FileNames) == null)
                    break;
                MetroMessageBox.Show("Duplicate Tag", "Please enter a name that is different from the original and that is not in use.");
            }

            // Make a tag container for the tag and then inject it
            // TODO: A lot of this was copied and pasted from the tag extraction code...need to clean things up
            var container = new TagContainer();
            using (var stream = _mapManager.OpenReadWrite())
            {
                // Get the plugin path
                string className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(tag.RawTag.Class.Magic)).Trim();
                string pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins",
                    _buildInfo.Settings.GetSetting<string>("plugins"), className);

                // Extract data blocks
                var builder = new DataBlockBuilder(stream, tag.RawTag, _cacheFile, _buildInfo);
                using (XmlReader pluginReader = XmlReader.Create(pluginPath))
                    AssemblyPluginLoader.LoadPlugin(pluginReader, builder);
                foreach (var block in builder.DataBlocks)
                {
                    // Remove non-datablock fixups because those are still valid
                    // TODO: A better approach might be to just make DataBlockBuilder ignore these in the first place
                    block.StringIDFixups.Clear();
                    block.ShaderFixups.Clear();
                    block.ResourceFixups.Clear();
                    block.TagFixups.Clear();
                    container.AddDataBlock(block);
                }
                var extracted = new ExtractedTag(tag.RawTag.Index, tag.RawTag.MetaLocation.AsPointer(), tag.RawTag.Class.Magic, newName);
                container.AddTag(extracted);

                // Now inject the container
                var injector = new TagContainerInjector(_cacheFile, container);
                injector.InjectTag(extracted, stream);
                injector.SaveChanges(stream);
            }

            LoadTags();
            MetroMessageBox.Show("Duplicate Tag", "Tag duplicated successfully!");
        }
Пример #21
0
        private static void ReadBlocks(IReader reader, ContainerReader containerFile, TagContainer tags)
        {
            while (containerFile.NextBlock())
            {
                switch (containerFile.BlockName)
                {
                case "data":
                    // Data block
                    tags.AddDataBlock(ReadDataBlock(reader, containerFile.BlockVersion));
                    break;

                case "tag!":
                    // Extracted tag
                    tags.AddTag(ReadTag(reader, containerFile.BlockVersion));
                    break;

                case "rspg":
                    // Resource page
                    tags.AddResourcePage(ReadResourcePage(reader, containerFile.BlockVersion));
                    break;

                case "rsrc":
                    // Resource info
                    tags.AddResource(ReadResource(reader, containerFile.BlockVersion));
                    break;
                }
            }
        }