예제 #1
0
        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();
                    }
                }
            }
        }
예제 #2
0
        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") + ".");
        }
예제 #3
0
        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;
                }
            }
        }
예제 #4
0
        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.");
            }
        }
예제 #5
0
        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();
                    }
                }
            }
        }
예제 #6
0
        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.");
        }
예제 #7
0
        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.");
            }
        }
예제 #8
0
        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;
                }
            }
        }