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; } } }
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(); } }
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(); }
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; }
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(); } }
public TagContainerInjector(ICacheFile cacheFile, TagContainer container) { _cacheFile = cacheFile; _container = container; }
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(); } }
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(); } }
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)."); }
public TagContainerInjector(ICacheFile cacheFile, TagContainer container) { _cacheFile = cacheFile; _languageCache = new CachedLanguagePackLoader(cacheFile.Languages); _container = container; }
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(); } }
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(); } }
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(); } }
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)."); }
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(); } }
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(); } }
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(); } }
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(); } }
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!"); }
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; } } }