mirror of
https://github.com/fadden/6502bench.git
synced 2025-03-13 04:36:18 +00:00
Visualizer improvements
Various changes: - Generally treat visualization sets like long comments and notes when it comes to defining data region boundaries. (We were doing this for selections; now we're also doing it for format-as-word and in the data analyzer when scanning for strings/fill.) - Clear the visualization cache when the address map is altered. This is necessary for visualizers that dereference addresses. - Read the Apple II screen image from a series of addresses rather than a series of offsets. This allows it to work when the image is contiguous in memory but split into chunks in the file. - Put 1 pixel of padding around the images in the main code list, so they don't blend into the background. - Remember the last visualizer used, so we can re-use it the next time the user selects "new". - Move min-size hack from Loaded to ContentRendered, as it apparently spoils CenterOwner placement.
This commit is contained in:
parent
af4ec49c9b
commit
1cdb31de32
@ -552,7 +552,7 @@ namespace SourceGen {
|
||||
Debug.Assert(attr.Length > 0);
|
||||
offset += attr.Length;
|
||||
}
|
||||
} else if (attr.Symbol != null || mProject.HasCommentOrNote(offset)) {
|
||||
} else if (attr.Symbol != null || mProject.HasCommentNoteOrVis(offset)) {
|
||||
// In an uncategorized area, but we want to break at this byte
|
||||
// so the user or auto label doesn't get buried in the middle of
|
||||
// a large chunk.
|
||||
|
@ -1798,14 +1798,16 @@ namespace SourceGen {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the offset has a long comment or note. Used for determining how to
|
||||
/// split up a data area. Currently not returning true for an end-of-line comment.
|
||||
/// Returns true if the offset has a long comment, note, or visualization. Used for
|
||||
/// determining how to split up a data area.
|
||||
/// Currently not returning true for an end-of-line comment.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of interest.</param>
|
||||
/// <returns>True if a comment or note was found.</returns>
|
||||
public bool HasCommentOrNote(int offset) {
|
||||
/// <returns>True if a comment, note, or visualization was found.</returns>
|
||||
public bool HasCommentNoteOrVis(int offset) {
|
||||
return (LongComments.ContainsKey(offset) ||
|
||||
Notes.ContainsKey(offset));
|
||||
Notes.ContainsKey(offset) ||
|
||||
VisualizationSets.ContainsKey(offset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1986,6 +1988,10 @@ namespace SourceGen {
|
||||
Debug.WriteLine("Map offset +" + offset.ToString("x6") + " to $" +
|
||||
((int)newValue).ToString("x6"));
|
||||
|
||||
// Visualization generators in extension scripts could be chasing
|
||||
// addresses. Give them a chance to update.
|
||||
ClearVisualizationCache();
|
||||
|
||||
// ignore affectedOffsets
|
||||
Debug.Assert(uc.ReanalysisRequired ==
|
||||
UndoableChange.ReanalysisScope.CodeAndData);
|
||||
@ -2238,12 +2244,7 @@ namespace SourceGen {
|
||||
// run through here.)
|
||||
}
|
||||
if (needExtScriptReload) {
|
||||
// Clear all the Visualization thumbnails. We don't do GUI
|
||||
// stuff in here, so this just sets a flag.
|
||||
foreach (KeyValuePair<int, VisualizationSet> kvp
|
||||
in VisualizationSets) {
|
||||
kvp.Value.RefreshNeeded();
|
||||
}
|
||||
ClearVisualizationCache();
|
||||
}
|
||||
}
|
||||
// ignore affectedOffsets
|
||||
@ -2292,6 +2293,15 @@ namespace SourceGen {
|
||||
return needReanalysis;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all visualization cached images.
|
||||
/// </summary>
|
||||
private void ClearVisualizationCache() {
|
||||
foreach (KeyValuePair<int, VisualizationSet> kvp in VisualizationSets) {
|
||||
kvp.Value.RefreshNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all symbolic references to the old label. Call this after replacing
|
||||
/// mAnattribs[labelOffset].Symbol.
|
||||
|
@ -2344,7 +2344,7 @@ namespace SourceGen {
|
||||
Anattrib nextAttr = mProject.GetAnattrib(nextOffset);
|
||||
// This must match what GroupedOffsetSetFromSelected() does.
|
||||
if (!mProject.UserLabels.ContainsKey(nextOffset) &&
|
||||
!mProject.HasCommentOrNote(nextOffset) &&
|
||||
!mProject.HasCommentNoteOrVis(nextOffset) &&
|
||||
thisAttr.Address == nextAttr.Address - 1) {
|
||||
// Good to go.
|
||||
Debug.WriteLine("Grabbing second byte from +" + nextOffset.ToString("x6"));
|
||||
@ -3329,11 +3329,8 @@ namespace SourceGen {
|
||||
// for the uncategorized data analyzer, but very annoying if you want to
|
||||
// slap a 16-bit numeric format on all entries in a table.
|
||||
groupNum++;
|
||||
} else if (mProject.HasCommentOrNote(offset)) {
|
||||
// Don't carry across a long comment or note.
|
||||
groupNum++;
|
||||
} else if (mProject.VisualizationSets.ContainsKey(offset)) {
|
||||
// Don't carry across a visualization.
|
||||
} else if (mProject.HasCommentNoteOrVis(offset)) {
|
||||
// Don't carry across a long comment, note, or visualization.
|
||||
groupNum++;
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ namespace RuntimeData.Apple {
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateScreen(ReadOnlyDictionary<string, object> parms) {
|
||||
const int RAW_IMAGE_SIZE = 0x1ff8;
|
||||
//const int RAW_IMAGE_SIZE = 0x1ff8;
|
||||
const int HR_WIDTH = 280;
|
||||
const int HR_BYTE_WIDTH = HR_WIDTH / 7;
|
||||
const int HR_HEIGHT = 192;
|
||||
@ -261,24 +261,34 @@ namespace RuntimeData.Apple {
|
||||
return null;
|
||||
}
|
||||
|
||||
int lastOffset = offset + RAW_IMAGE_SIZE - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Bitmap runs off end of file (last offset +" +
|
||||
lastOffset.ToString("x6") + ")");
|
||||
return null;
|
||||
}
|
||||
//int lastOffset = offset + RAW_IMAGE_SIZE - 1;
|
||||
//if (lastOffset >= mFileData.Length) {
|
||||
// mAppRef.ReportError("Bitmap runs off end of file (last offset +" +
|
||||
// lastOffset.ToString("x6") + ")");
|
||||
// return null;
|
||||
//}
|
||||
|
||||
// Linearize the data.
|
||||
// Linearize the data. To handle programs that move themselves around before
|
||||
// executing we use the address translator (e.g. the title screen in Space Eggs
|
||||
// is contiguous in memory but split in half in the file). This is slower, but
|
||||
// mAddrTrans is a local (not proxy) object, so it's not too bad.
|
||||
byte[] buf = new byte[HR_BYTE_WIDTH * HR_HEIGHT];
|
||||
int outIdx = 0;
|
||||
int baseAddr = mAddrTrans.OffsetToAddress(offset);
|
||||
for (int row = 0; row < HR_HEIGHT; row++) {
|
||||
// If row is ABCDEFGH, we want pppFGHCD EABAB000 (where p is zero for us).
|
||||
// If row is ABCDEFGH, we want pppFGHCD EABAB000 (where p would be $20/$40).
|
||||
int low = ((row & 0xc0) >> 1) | ((row & 0xc0) >> 3) | ((row & 0x08) << 4);
|
||||
int high = ((row & 0x07) << 2) | ((row & 0x30) >> 4);
|
||||
int addr = (high << 8) | low;
|
||||
int rowAddr = baseAddr + ((high << 8) | low);
|
||||
|
||||
for (int col = 0; col < HR_BYTE_WIDTH; col++) {
|
||||
buf[outIdx++] = mFileData[offset + addr + col];
|
||||
int srcOffset = mAddrTrans.AddressToOffset(offset, rowAddr + col);
|
||||
if (srcOffset < 0) {
|
||||
mAppRef.ReportError("Address $" + (rowAddr + col).ToString("x4") +
|
||||
" is outside of file");
|
||||
return null;
|
||||
}
|
||||
buf[outIdx++] = mFileData[srcOffset];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,13 +69,6 @@ and 65816 code. The official web site is
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="visualization.html">Visualizations</a>
|
||||
<ul>
|
||||
<li><a href="visualization.html#overview">Overview</a></li>
|
||||
<li><a href="visualization.html#vis-and-sets">Visualizations and Visualization Sets</a></li>
|
||||
<li><a href="visualization.html#runtime">Scripts Included with SourceGen</a></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="editors.html">Editors</a>
|
||||
<ul>
|
||||
<li><a href="editors.html#address">Edit Address</a></li>
|
||||
@ -95,6 +88,13 @@ and 65816 code. The official web site is
|
||||
<li><a href="editors.html#lvtable">Edit Local Variable Table</a></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="visualization.html">Visualizations</a>
|
||||
<ul>
|
||||
<li><a href="visualization.html#overview">Overview</a></li>
|
||||
<li><a href="visualization.html#vis-and-sets">Visualizations and Visualization Sets</a></li>
|
||||
<li><a href="visualization.html#runtime">Scripts Included with SourceGen</a></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="codegen.html">Code Generation & Assembly</a>
|
||||
<ul>
|
||||
<li><a href="codegen.html#supported">Supported Assemblers</a>
|
||||
|
@ -30,10 +30,14 @@ include them in your project.</p>
|
||||
<p>The project file doesn't store the converted graphics. Instead, the
|
||||
project file holds a string that identifies the converter, and a list of
|
||||
parameters that are passed to the converter. Images are generated when
|
||||
the project is first opened, and updated if the set of loaded extension
|
||||
scripts changes.</p>
|
||||
the project is first opened, and updated when certain things change in
|
||||
the project.</p>
|
||||
<p>Visualizations are not included in generated assembly output. They
|
||||
may be included in HTML exports.</p>
|
||||
<p>Because visualizations are associated with a specific file offset,
|
||||
they will become "hidden" if the offset isn't at the start of a line,
|
||||
e.g. it's in the middle of a multi-byte instruction or data item. The
|
||||
editors will try to prevent you from doing this.</p>
|
||||
|
||||
|
||||
<h2><a name="vis-and-sets">Visualizations and Visualization Sets</a></h2>
|
||||
@ -43,7 +47,9 @@ assembled output, and do not change how code is analyzed. They are
|
||||
contained in sets that are placed at arbitrary offsets. Each set can
|
||||
contain multiple items. For example, if a file has data for
|
||||
10 bitmaps, you can place a visualization near each, or create a single
|
||||
visualization set with all 10 items and put it at the start of the file.</p>
|
||||
visualization set with all 10 items and put it at the start of the file.
|
||||
You can display a visualization near the instructions that perform the
|
||||
drawing.</p>
|
||||
|
||||
<p>To create a visualization set, select a code or data line, and use
|
||||
Actions > Create/Edit Visualization Set. To edit a visualization set,
|
||||
@ -115,7 +121,11 @@ arrangements are common. The script defines three generators:</p>
|
||||
converted as monochrome, and have a 1-pixel transparent gap
|
||||
between elements.</li>
|
||||
<li><b>Hi-Res Screen Image</b> - used for 8KiB screen images. The
|
||||
data is linearized and converted to a 280x192 bitmap.</li>
|
||||
data is linearized and converted to a 280x192 bitmap. Because
|
||||
images are relatively large, the generator does not require them
|
||||
to be contiguous in the file, i.e. two halves of the image can be
|
||||
in different parts of the file so long as they end up contiguous
|
||||
in memory.</li>
|
||||
</ul>
|
||||
|
||||
<p>Widths are specified in bytes, not pixels. Each byte represents 7
|
||||
|
@ -21,7 +21,7 @@
|
||||
"LongComments":{
|
||||
},
|
||||
"Notes":{
|
||||
"213":{
|
||||
"222":{
|
||||
"Text":"Bitmaps here","BoxMode":false,"MaxWidth":80,"BackgroundColor":-256}},
|
||||
"UserLabels":{
|
||||
},
|
||||
|
@ -106,7 +106,7 @@ See also https://github.com/fadden/DisasmUiTest
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border BorderThickness="1" Margin="8,0,0,0"
|
||||
<Border BorderThickness="1" Margin="8,0,0,0" Padding="1"
|
||||
Background="{StaticResource BitmapBackground}">
|
||||
<Image Width="64" Height="64" Source="{Binding CachedImage}"
|
||||
RenderOptions.BitmapScalingMode="NearestNeighbor"/>
|
||||
|
@ -25,7 +25,7 @@ limitations under the License.
|
||||
Title="Edit Visualization"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="CanResizeWithGrip"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
Loaded="Window_Loaded"
|
||||
ContentRendered="Window_ContentRendered"
|
||||
Closed="Window_Closed">
|
||||
|
||||
<Window.Resources>
|
||||
|
@ -42,6 +42,11 @@ namespace SourceGen.WpfGui {
|
||||
private Visualization mOrigVis;
|
||||
private string mOrigTag;
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for last visualizer we used, for the benefit of "new".
|
||||
/// </summary>
|
||||
private static string sLastVisIdent = string.Empty;
|
||||
|
||||
private Brush mDefaultLabelColor = SystemColors.WindowTextBrush;
|
||||
private Brush mErrorLabelColor = Brushes.Red;
|
||||
|
||||
@ -168,7 +173,7 @@ namespace SourceGen.WpfGui {
|
||||
mFormatter = formatter;
|
||||
mSetOffset = setOffset;
|
||||
mOrigVis = vis;
|
||||
mOrigTag = vis.Tag;
|
||||
mOrigTag = (vis == null) ? string.Empty : vis.Tag;
|
||||
|
||||
mScriptSupport = new ScriptSupport(this);
|
||||
mProject.PrepareScripts(mScriptSupport);
|
||||
@ -180,7 +185,7 @@ namespace SourceGen.WpfGui {
|
||||
TagString = "vis" + mSetOffset.ToString("x6");
|
||||
}
|
||||
|
||||
int visSelection = 0;
|
||||
int visSelection = -1;
|
||||
VisualizationList = new List<VisualizationItem>();
|
||||
List<IPlugin> plugins = proj.GetActivePlugins();
|
||||
foreach (IPlugin chkPlug in plugins) {
|
||||
@ -190,6 +195,10 @@ namespace SourceGen.WpfGui {
|
||||
IPlugin_Visualizer vplug = (IPlugin_Visualizer)chkPlug;
|
||||
foreach (VisDescr descr in vplug.GetVisGenDescrs()) {
|
||||
if (vis != null && vis.VisGenIdent == descr.Ident) {
|
||||
// found matching descriptor, set selection to this
|
||||
visSelection = VisualizationList.Count;
|
||||
} else if (visSelection < 0 && descr.Ident == sLastVisIdent) {
|
||||
// we used this one last time, use it if nothing better comes along
|
||||
visSelection = VisualizationList.Count;
|
||||
}
|
||||
VisualizationList.Add(new VisualizationItem(vplug, descr));
|
||||
@ -197,6 +206,9 @@ namespace SourceGen.WpfGui {
|
||||
}
|
||||
|
||||
// Set the selection. This should cause the sel change event to fire.
|
||||
if (visSelection < 0) {
|
||||
visSelection = 0;
|
||||
}
|
||||
visComboBox.SelectedIndex = visSelection;
|
||||
}
|
||||
|
||||
@ -253,7 +265,7 @@ namespace SourceGen.WpfGui {
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
private void Window_ContentRendered(object sender, EventArgs e) {
|
||||
// https://stackoverflow.com/a/31407415/294248
|
||||
// After the window's size has been established to minimally wrap the elements,
|
||||
// we set the minimum width to the current width, and un-freeze the preview image
|
||||
@ -284,6 +296,8 @@ namespace SourceGen.WpfGui {
|
||||
NewVis = new Visualization(trimTag, item.VisDescriptor.Ident, valueDict);
|
||||
NewVis.CachedImage = (BitmapSource)previewImage.Source;
|
||||
|
||||
sLastVisIdent = NewVis.VisGenIdent;
|
||||
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user