private void UpdateMeta(MetaWriter.SaveType type, bool onlyUpdateChanged, bool showActionDialog = true) { if (type == MetaWriter.SaveType.File) { if (!ConfirmNewStringIds()) { return; } using (IStream stream = _fileManager.OpenReadWrite()) { #if DEBUG_SAVE_ALL MetaWriter metaUpdate = new MetaWriter(writer, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, type, null, _stringIdTrie); #else var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, type, _fileChanges, _stringIdTrie); #endif metaUpdate.WriteFields(_pluginVisitor.Values); _cache.SaveChanges(stream); _fileChanges.MarkAllUnchanged(); } if (showActionDialog) { MetroMessageBox.Show("Meta Saved", "The metadata has been saved back to the original file."); } } else if (_rteProvider != null) { using (IStream metaStream = _rteProvider.GetMetaStream(_cache)) { if (metaStream != null) { FieldChangeSet changes = onlyUpdateChanged ? _memoryChanges : null; var metaUpdate = new MetaWriter(metaStream, _tag.RawTag.MetaLocation.AsPointer(), _cache, _buildInfo, type, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); if (showActionDialog) { if (onlyUpdateChanged) { MetroMessageBox.Show("Meta Poked", "All changed metadata has been poked to the game."); } else { MetroMessageBox.Show("Meta Poked", "The metadata has been poked to the game."); } } } else { ShowConnectionError(); } } } }
private void AllocateDataRefCommand_Executed(object sender, ExecutedRoutedEventArgs e) { if (_cache.Engine < EngineType.SecondGeneration || (_cache.Engine == EngineType.ThirdGeneration && _cache.HeaderSize == 0x800)) { MetroMessageBox.Show("Data Reference Allocator", "Only second and third generation cache files are currently supported by the data reference allocator."); return; } var field = GetWrappedField(e.OriginalSource) as DataRef; if (field == null) { return; } var oldLength = field.Length; var newLength = MetroDataRefAllocator.Show(_cache, field); if (!newLength.HasValue) { return; // Canceled } var oldAddress = field.DataAddress; long newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Allocate a new block as to not potentially disturb shared uses newAddress = _cache.Allocator.Allocate(newLength.Value, stream); _cache.SaveChanges(stream); } // Changing these causes a read from the file, so the stream has to be closed first field.Length = newLength.Value; field.DataAddress = newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Force a save back to the file var changes = new FieldChangeSet(); changes.MarkChanged(field); var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, MetaWriter.SaveType.File, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); _fileChanges.MarkUnchanged(field); } MetroMessageBox.Show("Data Reference Allocator - Assembly", "The data was allocated successfully. Its address is 0x" + newAddress.ToString("X8") + "."); }
public void RefreshEditor(MetaReader.LoadType type) { // Load Plugin Path string groupName = VariousFunctions.SterilizeTagGroupName(CharConstant.ToString(_tag.RawTag.Group.Magic)).Trim(); _pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins", _buildInfo.Settings.GetSetting <string>("plugins"), groupName); if (!File.Exists(_pluginPath) && _buildInfo.Settings.PathExists("fallbackPlugins")) { _pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins", _buildInfo.Settings.GetSetting <string>("fallbackPlugins"), groupName); } if (_pluginPath == null || !File.Exists(_pluginPath)) { UpdateMetaButtons(false); StatusUpdater.Update("Plugin doesn't exist. It can't be loaded for this tag."); return; } // Store the current search selection so it can be restored int searchSelectedItem = comboSearchResults.SelectedIndex; // Set the stream manager and base offset to use based upon the LoadType IStreamManager streamManager = null; long baseOffset = 0; switch (type) { case MetaReader.LoadType.File: streamManager = _fileManager; baseOffset = (uint)_tag.RawTag.MetaLocation.AsOffset(); break; case MetaReader.LoadType.Memory: if (_rteProvider == null) { goto default; } if (_rteProvider.GetMetaStream(_cache) == null) { ShowConnectionError(); return; } streamManager = new RTEStreamManager(_rteProvider, _cache); baseOffset = _tag.RawTag.MetaLocation.AsPointer(); break; default: MetroMessageBox.Show("Not Supported", "That feature is not supported for this game."); return; } // Load Plugin File using (XmlReader xml = XmlReader.Create(_pluginPath)) { _pluginVisitor = new ThirdGenPluginVisitor(_tags, _stringIdTrie, _cache.MetaArea, App.AssemblyStorage.AssemblySettings.PluginsShowInvisibles); AssemblyPluginLoader.LoadPlugin(xml, _pluginVisitor); } _changeTracker = new FieldChangeTracker(); _fileChanges = new FieldChangeSet(); _memoryChanges = new FieldChangeSet(); var metaReader = new MetaReader(streamManager, baseOffset, _cache, _buildInfo, type, _fileChanges); _flattener = new TagBlockFlattener(metaReader, _changeTracker, _fileChanges); _flattener.Flatten(_pluginVisitor.Values); metaReader.ReadFields(_pluginVisitor.Values); panelMetaComponents.ItemsSource = _pluginVisitor.Values; // Start monitoring fields for changes _changeTracker.RegisterChangeSet(_fileChanges); _changeTracker.RegisterChangeSet(_memoryChanges); _changeTracker.Attach(_pluginVisitor.Values); // Update Meta Toolbar UpdateMetaButtons(true); // Refresh search if needed if (searchSelectedItem != -1) { SearchTimer(null); if (searchSelectedItem <= (comboSearchResults.Items.Count - 1)) { comboSearchResults.SelectedIndex = searchSelectedItem; } } }
private void ReallocateBlockCommand_Executed(object sender, ExecutedRoutedEventArgs e) { if (_cache.Engine < EngineType.SecondGeneration || (_cache.Engine == EngineType.ThirdGeneration && _cache.HeaderSize == 0x800)) { MetroMessageBox.Show("Tag Block Reallocator", "Only second and third generation cache files are currently supported by the block reallocator."); return; } var field = GetWrappedField(e.OriginalSource) as TagBlockData; if (field == null) { return; } var oldCount = field.Length; var newCount = MetroTagBlockReallocator.Show(_cache, field); if (newCount == null || newCount == oldCount) { return; // Canceled } var oldAddress = field.FirstElementAddress; var oldSize = field.Length * field.ElementSize; var newSize = (int)newCount * field.ElementSize; long newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Reallocate the block newAddress = _cache.Allocator.Reallocate(oldAddress, (int)oldSize, (int)newSize, (uint)field.Align, stream); _cache.SaveChanges(stream); // If the block was made larger, zero extra data and null tagrefs if (newAddress != 0 && newSize > oldSize) { stream.SeekTo(_cache.MetaArea.PointerToOffset(newAddress) + oldSize); StreamUtil.Fill(stream, 0, (int)(newSize - oldSize)); var tagRefLayout = _buildInfo.Layouts.GetLayout("tag reference"); var groupOffset = tagRefLayout.GetFieldOffset("tag group magic"); var datumOffset = tagRefLayout.GetFieldOffset("datum index"); //go through each new page and write null for any tagrefs for (int i = oldCount; i < newCount; i++) { var entryStart = _cache.MetaArea.PointerToOffset(newAddress) + (field.ElementSize * i); foreach (MetaField mf in field.Template) { if (mf.GetType() != typeof(TagRefData)) { continue; } var tagref = (TagRefData)mf; if (tagref.WithGroup) { stream.SeekTo(entryStart + tagref.Offset + groupOffset); stream.WriteInt32(-1); stream.SeekTo(entryStart + tagref.Offset + datumOffset); stream.WriteInt32(-1); } else { //no group, write to field offset without adding anything stream.SeekTo(entryStart + tagref.Offset); stream.WriteInt32(-1); } } } } } // Changing these causes a read from the file, so the stream has to be closed first field.Length = (int)newCount; field.FirstElementAddress = newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Force a save back to the file var changes = new FieldChangeSet(); changes.MarkChanged(field); var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, MetaWriter.SaveType.File, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); _fileChanges.MarkUnchanged(field); } if (newAddress == oldAddress) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was resized successfully. Its address did not change."); } else if (oldAddress == 0) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was allocated successfully. Its address is 0x" + newAddress.ToString("X8") + "."); } else if (newAddress != 0) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was reallocated successfully. Its new address is 0x" + newAddress.ToString("X8") + "."); } else { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was freed successfully."); } }
private void UpdateMeta(MetaWriter.SaveType type, bool onlyUpdateChanged, bool showActionDialog = true) { if (type == MetaWriter.SaveType.File) { if (!ConfirmNewStringIds()) { return; } using (IStream stream = _fileManager.OpenReadWrite()) { #if DEBUG_SAVE_ALL MetaWriter metaUpdate = new MetaWriter(writer, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, type, null, _stringIdTrie); #else var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, type, _fileChanges, _stringIdTrie); #endif metaUpdate.WriteFields(_pluginVisitor.Values); _cache.SaveChanges(stream); _fileChanges.MarkAllUnchanged(); } if (showActionDialog) { MetroMessageBox.Show("Tag Saved", "The changes have been saved back to the original file." + (_buildInfo.UsesCompression && _cache.Engine == EngineType.SecondGeneration ? "\r\n\r\nNote: This file must be compressed from the Tools menu before attempting to load ingame." : "")); } } else if (_rteProvider != null) { var rteProvider = _rteProvider; if (App.AssemblyStorage.AssemblyNetworkPoke.NetworkRteProvider != null) { rteProvider = App.AssemblyStorage.AssemblyNetworkPoke.NetworkRteProvider; } using (IStream metaStream = rteProvider.GetMetaStream(_cache)) { if (metaStream != null) { FieldChangeSet changes = onlyUpdateChanged ? _memoryChanges : null; var metaUpdate = new MetaWriter(metaStream, _tag.RawTag.MetaLocation.AsPointer(), _cache, _buildInfo, type, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); if (showActionDialog) { if (onlyUpdateChanged) { StatusUpdater.Update("All changed fields have been poked to the game."); } else { StatusUpdater.Update("The changes have been poked to the game."); } } } else { ShowConnectionError(); } } } }
private void IsolateDataRefCommand_Executed(object sender, ExecutedRoutedEventArgs e) { if (_cache.Engine < EngineType.SecondGeneration || (_cache.Engine == EngineType.ThirdGeneration && _cache.HeaderSize == 0x800)) { MetroMessageBox.Show("Data Reference Isolation", "Only second and third generation cache files are currently supported."); return; } var field = GetWrappedField(e.OriginalSource) as DataRef; if (field == null) { return; } var oldAddress = field.DataAddress; int size = field.Length; if (oldAddress == 0 || size == 0) { MetroMessageBox.Show("Data Reference Isolation", "Cannot isolate: data is null."); return; } var result = MetroMessageBox.Show("Data Reference Isolation", "Are you sure you want to copy this data to a new location?", MetroMessageBox.MessageBoxButtons.OkCancel); if (result != MetroMessageBox.MessageBoxResult.OK) { return; } long newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Allocate the data newAddress = _cache.Allocator.Allocate(size, stream); _cache.SaveChanges(stream); //copy data stream.SeekTo(_cache.MetaArea.PointerToOffset(oldAddress)); var data = stream.ReadBlock(size); stream.SeekTo(_cache.MetaArea.PointerToOffset(newAddress)); stream.WriteBlock(data); } // Changing these causes a read from the file, so the stream has to be closed first field.DataAddress = newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Force a save back to the file var changes = new FieldChangeSet(); changes.MarkChanged(field); var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, MetaWriter.SaveType.File, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); _fileChanges.MarkUnchanged(field); } MetroMessageBox.Show("Data Reference Isolation - Assembly", "The data reference was isolated successfully."); }
private void ReallocateCommand_Executed(object sender, ExecutedRoutedEventArgs e) { var field = GetWrappedField(e.OriginalSource) as ReflexiveData; if (field == null) { return; } var newCount = MetroTagBlockReallocator.Show(_cache, field); if (newCount == null || (int)newCount == field.Length) { return; // Canceled } var oldAddress = field.FirstEntryAddress; var oldSize = field.Length * field.EntrySize; var newSize = (int)newCount * field.EntrySize; uint newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Reallocate the block newAddress = _cache.Allocator.Reallocate(oldAddress, (int)oldSize, (int)newSize, (uint)field.Align, stream); _cache.SaveChanges(stream); // If the block was made larger, zero extra data if (newAddress != 0 && newSize > oldSize) { stream.SeekTo(_cache.MetaArea.PointerToOffset(newAddress) + oldSize); StreamUtil.Fill(stream, 0, (int)(newSize - oldSize)); } } // Changing these causes a read from the file, so the stream has to be closed first field.Length = (int)newCount; field.FirstEntryAddress = newAddress; using (var stream = _fileManager.OpenReadWrite()) { // Force a save back to the file var changes = new FieldChangeSet(); changes.MarkChanged(field); var metaUpdate = new MetaWriter(stream, (uint)_tag.RawTag.MetaLocation.AsOffset(), _cache, _buildInfo, MetaWriter.SaveType.File, changes, _stringIdTrie); metaUpdate.WriteFields(_pluginVisitor.Values); _fileChanges.MarkUnchanged(field); } if (newAddress == oldAddress) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was resized successfully. Its address did not change."); } else if (oldAddress == 0) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was allocated successfully. Its address is 0x" + newAddress.ToString("X8") + "."); } else if (newAddress != 0) { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was reallocated successfully. Its new address is 0x" + newAddress.ToString("X8") + "."); } else { MetroMessageBox.Show("Tag Block Reallocator - Assembly", "The tag block was freed successfully."); } }
public void RefreshEditor(MetaReader.LoadType type) { if (!File.Exists(_pluginPath)) { UpdateMetaButtons(false); StatusUpdater.Update("Plugin doesn't exist. It can't be loaded for this tag."); return; } // Store the current search selection so it can be restored int searchSelectedItem = comboSearchResults.SelectedIndex; // Set the stream manager and base offset to use based upon the LoadType IStreamManager streamManager = null; uint baseOffset = 0; uint headerOffset = 0; switch (type) { case MetaReader.LoadType.File: streamManager = _fileManager; baseOffset = (uint)_tag.RawTag.MetaLocation.AsOffset(); headerOffset = _tag.RawTag.HeaderLocation == null ? 0 : (uint)_tag.RawTag.HeaderLocation.AsOffset(); break; case MetaReader.LoadType.Memory: if (_rteProvider == null) { goto default; } using (var testStream = _rteProvider.GetMetaStream(_cache, _tag.RawTag)) { if (testStream == null) { ShowConnectionError(); return; } } streamManager = new RTEStreamManager(_rteProvider, _cache, _tag.RawTag); baseOffset = _tag.RawTag.MetaLocation.AsPointer(); break; default: MetroMessageBox.Show("Not Supported", "That feature is not supported for this game."); return; } // Load Plugin File using (XmlReader xml = XmlReader.Create(_pluginPath)) { _pluginVisitor = new ThirdGenPluginVisitor(_tags, _stringIdTrie, _cache.MetaArea, App.AssemblyStorage.AssemblySettings.PluginsShowInvisibles); AssemblyPluginLoader.LoadPlugin(xml, _pluginVisitor); } _changeTracker = new FieldChangeTracker(); _fileChanges = new FieldChangeSet(); _memoryChanges = new FieldChangeSet(); var metaReader = new MetaReader(streamManager, headerOffset, baseOffset, _cache, _buildInfo, type, _fileChanges); _flattener = new ReflexiveFlattener(metaReader, _changeTracker, _fileChanges); _flattener.Flatten(_pluginVisitor.Values); metaReader.ReadFields(_pluginVisitor.Values); panelMetaComponents.ItemsSource = _pluginVisitor.Values; // Start monitoring fields for changes _changeTracker.RegisterChangeSet(_fileChanges); _changeTracker.RegisterChangeSet(_memoryChanges); _changeTracker.Attach(_pluginVisitor.Values); // Update Meta Toolbar UpdateMetaButtons(true); // Refresh search if needed if (searchSelectedItem != -1) { SearchTimer(null); if (searchSelectedItem <= (comboSearchResults.Items.Count - 1)) { comboSearchResults.SelectedIndex = searchSelectedItem; } } }