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 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."); } }