diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs index b7c39b1..c19c4e1 100644 --- a/SourceGen/DisasmProject.cs +++ b/SourceGen/DisasmProject.cs @@ -91,15 +91,20 @@ namespace SourceGen { public Dictionary UserLabels { get; private set; } /// - /// Local variable tables. + /// Local variable tables. Uses file offset as key. /// public SortedList LvTables { get; private set; } /// - /// Format descriptors for operands and data items; uses file offset as key. + /// Format descriptors for operands and data items. Uses file offset as key. /// public SortedList OperandFormats { get; private set; } + /// + /// Visualization sets. Uses file offset as key. + /// + public SortedList VisualizationSets { get; private set; } + /// /// Project properties. Includes CPU type, platform symbol file names, project /// symbols, etc. @@ -243,6 +248,7 @@ namespace SourceGen { UserLabels = new Dictionary(); OperandFormats = new SortedList(); LvTables = new SortedList(); + VisualizationSets = new SortedList(); ProjectProps = new ProjectProperties(); SymbolTable = new SymbolTable(); @@ -2248,6 +2254,22 @@ namespace SourceGen { UndoableChange.ReanalysisScope.DataOnly); } break; + case UndoableChange.ChangeType.SetVisualizationSet: { + VisualizationSets.TryGetValue(offset, out VisualizationSet current); + if (current != (VisualizationSet)oldValue) { + Debug.WriteLine("GLITCH: old visSet value mismatch: current=" + + current + " old=" + (VisualizationSet)oldValue); + Debug.Assert(false); + } + if (newValue == null) { + VisualizationSets.Remove(offset); + } else { + VisualizationSets[offset] = (VisualizationSet)newValue; + } + Debug.Assert(uc.ReanalysisRequired == + UndoableChange.ReanalysisScope.DisplayOnly); + } + break; default: break; } diff --git a/SourceGen/Exporter.cs b/SourceGen/Exporter.cs index b1adc25..0e2fa1c 100644 --- a/SourceGen/Exporter.cs +++ b/SourceGen/Exporter.cs @@ -314,6 +314,8 @@ namespace SourceGen { case LineListGen.Line.Type.Note: TextUtil.AppendPaddedString(sb, parts.Comment, mColStart[(int)Col.Label]); break; + case LineListGen.Line.Type.VisualizationSet: + break; // TODO(xyzzy) case LineListGen.Line.Type.Blank: break; default: @@ -617,6 +619,8 @@ namespace SourceGen { colPos = AddSpacedString(sb, colPos, mColStart[(int)Col.Label], cstr, parts.Comment.Length); break; + case LineListGen.Line.Type.VisualizationSet: + break; // TODO(xyzzy) case LineListGen.Line.Type.Blank: break; default: diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs index cbda18d..5c1e5ff 100644 --- a/SourceGen/LineListGen.cs +++ b/SourceGen/LineListGen.cs @@ -30,7 +30,7 @@ namespace SourceGen { /// public class LineListGen { /// - /// Color multiplier for Notes. + /// Color multiplier for Notes. Used for "dark" mode. /// public float NoteColorMultiplier { get; set; } = 1.0f; @@ -122,6 +122,7 @@ namespace SourceGen { // Additional metadata. LocalVariableTable = 1 << 8, + VisualizationSet = 1 << 9, } /// @@ -504,6 +505,13 @@ namespace SourceGen { case Line.Type.LocalVariableTable: parts = GenerateLvTableLine(line.FileOffset, line.SubLineIndex); break; + case Line.Type.VisualizationSet: + // TODO(xyzzy) + mProject.VisualizationSets.TryGetValue(line.FileOffset, + out VisualizationSet visSet); + parts = FormattedParts.CreateLongComment("!VISUALIZATION SET! " + + (visSet != null ? visSet.PlaceHolder : "???")); + break; case Line.Type.Blank: // Nothing to do. parts = FormattedParts.CreateBlankLine(); @@ -971,6 +979,9 @@ namespace SourceGen { StringListToLines(formatted, offset, Line.Type.LongComment, longComment.BackgroundColor, NoteColorMultiplier, lines); } + if (mProject.VisualizationSets.TryGetValue(offset, out VisualizationSet visSet)) { + lines.Add(new Line(offset, 0, Line.Type.VisualizationSet)); + } // Local variable tables come next. Defer rendering. if (mProject.LvTables.TryGetValue(offset, out LocalVariableTable lvt)) { diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index 3d92ccf..fcf4803 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -1491,6 +1491,11 @@ namespace SourceGen { EditLocalVariableTable(); } break; + case LineListGen.Line.Type.VisualizationSet: + if (CanEditVisualizationSet()) { + EditVisualizationSet(); + } + break; case LineListGen.Line.Type.Code: case LineListGen.Line.Type.Data: @@ -2058,6 +2063,25 @@ namespace SourceGen { } } + public void EditProjectProperties() { + string projectDir = string.Empty; + if (!string.IsNullOrEmpty(mProjectPathName)) { + projectDir = Path.GetDirectoryName(mProjectPathName); + } + EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject.ProjectProps, + projectDir, mOutputFormatter); + dlg.ShowDialog(); + ProjectProperties newProps = dlg.NewProps; + + // The dialog result doesn't matter, because the user might have hit "apply" + // before hitting "cancel". + if (newProps != null) { + UndoableChange uc = UndoableChange.CreateProjectPropertiesChange( + mProject.ProjectProps, newProps); + ApplyUndoableChanges(new ChangeSet(uc)); + } + } + public bool CanEditProjectSymbol() { if (SelectionAnalysis.mNumItemsSelected != 1) { return false; @@ -2119,22 +2143,37 @@ namespace SourceGen { } } - public void EditProjectProperties() { - string projectDir = string.Empty; - if (!string.IsNullOrEmpty(mProjectPathName)) { - projectDir = Path.GetDirectoryName(mProjectPathName); + public bool CanEditVisualizationSet() { + if (SelectionAnalysis.mNumItemsSelected != 1) { + return false; } - EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject.ProjectProps, - projectDir, mOutputFormatter); - dlg.ShowDialog(); - ProjectProperties newProps = dlg.NewProps; + EntityCounts counts = SelectionAnalysis.mEntityCounts; + // Single line, must be a visualization set. + LineListGen.Line.Type lineType = SelectionAnalysis.mLineType; + return (lineType == LineListGen.Line.Type.VisualizationSet || + lineType == LineListGen.Line.Type.Code || + lineType == LineListGen.Line.Type.Data); + } - // The dialog result doesn't matter, because the user might have hit "apply" - // before hitting "cancel". - if (newProps != null) { - UndoableChange uc = UndoableChange.CreateProjectPropertiesChange( - mProject.ProjectProps, newProps); - ApplyUndoableChanges(new ChangeSet(uc)); + public void EditVisualizationSet() { + int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex(); + int offset = CodeLineList[selIndex].FileOffset; + mProject.VisualizationSets.TryGetValue(offset, out VisualizationSet curVisSet); + + EditVisualizationSet dlg = new EditVisualizationSet(mMainWin, + curVisSet); + if (dlg.ShowDialog() != true) { + return; + } + if (curVisSet != dlg.NewVisSet) { + // New table, edited in place, or deleted. + UndoableChange uc = UndoableChange.CreateVisualizationSetChange(offset, + curVisSet, dlg.NewVisSet); + Debug.WriteLine("Change " + curVisSet + " to " + dlg.NewVisSet); + ChangeSet cs = new ChangeSet(uc); + ApplyUndoableChanges(cs); + } else { + Debug.WriteLine("No change to VisualizationSet"); } } @@ -3579,6 +3618,10 @@ namespace SourceGen { lineTypeStr = "???"; } break; + case LineListGen.Line.Type.VisualizationSet: + // TODO(xyzzy) + lineTypeStr = "visualization set"; + break; default: lineTypeStr = "???"; break; @@ -4007,7 +4050,9 @@ namespace SourceGen { continue; } - // Create a new user label symbol. + // Create a new user label symbol. We should not be creating a duplicate name, + // because user labels have priority over platform symbols when populating + // the symbol table. Symbol newSym = new Symbol(sym.Label, sym.Value, Symbol.Source.User, Symbol.Type.GlobalAddr, Symbol.LabelAnnotation.None); UndoableChange uc = UndoableChange.CreateLabelChange(offset, null, newSym); diff --git a/SourceGen/SourceGen.csproj b/SourceGen/SourceGen.csproj index 081d03c..9c76a6d 100644 --- a/SourceGen/SourceGen.csproj +++ b/SourceGen/SourceGen.csproj @@ -96,6 +96,7 @@ ShowText.xaml + AboutBox.xaml @@ -132,6 +133,9 @@ EditProjectProperties.xaml + + EditVisualizationSet.xaml + Export.xaml @@ -310,6 +314,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/SourceGen/UndoableChange.cs b/SourceGen/UndoableChange.cs index 35f6e5d..7810a8f 100644 --- a/SourceGen/UndoableChange.cs +++ b/SourceGen/UndoableChange.cs @@ -105,6 +105,9 @@ namespace SourceGen { // Adds, updates, or removes a local variable table. SetLocalVariableTable, + + // Adds, updates, or removes a visualization set. + SetVisualizationSet, } /// @@ -478,6 +481,28 @@ namespace SourceGen { return uc; } + /// + /// Creates an UndoableChange for a visualization set update. + /// + /// Affected offset. + /// Old visualization set. + /// New visualization set. + /// Change record. + public static UndoableChange CreateVisualizationSetChange(int offset, + VisualizationSet oldVisSet, VisualizationSet newVisSet) { + if (oldVisSet == newVisSet) { + Debug.WriteLine("No-op visualization set change"); + } + + UndoableChange uc = new UndoableChange(); + uc.Type = ChangeType.SetVisualizationSet; + uc.Offset = offset; + uc.OldValue = oldVisSet; + uc.NewValue = newVisSet; + uc.ReanalysisRequired = ReanalysisScope.DisplayOnly; // no change to code/data + return uc; + } + public override string ToString() { return "[UC type=" + Type + " offset=+" + (HasOffset ? Offset.ToString("x6") : "N/A") + "]"; diff --git a/SourceGen/VisualizationSet.cs b/SourceGen/VisualizationSet.cs new file mode 100644 index 0000000..2b11730 --- /dev/null +++ b/SourceGen/VisualizationSet.cs @@ -0,0 +1,56 @@ +/* + * Copyright 2019 faddenSoft + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SourceGen { + public class VisualizationSet { + // TODO(xyzzy) + public string PlaceHolder { get; private set; } + + public VisualizationSet(string placeHolder) { + PlaceHolder = placeHolder; + } + + + public override string ToString() { + return "[VS: " + PlaceHolder + "]"; + } + + public static bool operator ==(VisualizationSet a, VisualizationSet b) { + if (ReferenceEquals(a, b)) { + return true; // same object, or both null + } + if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) { + return false; // one is null + } + // All fields must be equal. + return a.PlaceHolder == b.PlaceHolder; + } + public static bool operator !=(VisualizationSet a, VisualizationSet b) { + return !(a == b); + } + public override bool Equals(object obj) { + return obj is VisualizationSet && this == (VisualizationSet)obj; + } + public override int GetHashCode() { + return PlaceHolder.GetHashCode(); + } + } +} diff --git a/SourceGen/WpfGui/EditVisualizationSet.xaml b/SourceGen/WpfGui/EditVisualizationSet.xaml new file mode 100644 index 0000000..63e1782 --- /dev/null +++ b/SourceGen/WpfGui/EditVisualizationSet.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + +