Visualization animations are now exported as animated GIFs. The
Windows stuff is a bit lame so I threw together some code that
stitches a bunch of GIFs together.
The GIF doesn't quite match the preview, because the preview scales
the individual frames, while the animated GIF uses the largest frame
as the size and is then scaled based on that. Animating frames of
differing sizes together is bound to be trouble anyway, so I'm not
sure how much to fret over this.
We now store Visualizations, VisualizationAnimations, and
VisualizationSets as three separate lists linked by tag strings.
WARNING: this breaks existing projects with visualizations. The
test projects have been updated.
The UI was moving items from the source list to the animation list,
but there's no reason why the same thing can't appear more than once.
You can no longer hit "Add" repeatedly to add multiple consecutive
items, but you can now multi-select in the source list to add several
things at once.
Bitmap animations are composed of a sequence of other visualizations.
This is all well and good until a visualization is deleted, at which
point all animations in all sets in the entire project have to be
checked and potentially changed, and perhaps even removed (if all of
the animation's members have been removed). This turns out to be
kind of annoying to deal with, but it's better to deal with it in
code than force the user to manually update broken animations.
This change adds thumbnails for the animations, currently generated
by offscreen composition. This approach doesn't work quite right.
This adds a new class and a rough GUI for the editor. Animated
visualizations take a collection of bitmaps and display them in
sequence. (This will eventually become an animated GIF.)
Fixed the issue where changes to tags in the set currently being
edited weren't visible to the tag uniqueness check when editing other
items in the same set.
We now generate GIF images for visualizations and add inline
references to them in the HTML output.
Images are scaled using the HTML img properties. This works well
on some browsers, but others insist on "smooth" scaling that blurs
out the pixels. This may require a workaround.
An extra blank line is now added above visualizations. This helps
keep the image and data visually grouped.
The Apple II bitmap test project was updated to have a visualization
set with multiple images at the top of the file.
(1) Added an option to limit the number of bytes per line. This is
handy for things like bitmaps, where you might want to put (say) 3
or 8 bytes per line to reflect the structure.
(2) Added an application setting that determines whether the screen
listing shows Merlin/ACME dense hex (20edfd) or 64tass/cc65 hex bytes
($20,$ed,$fd). Made the setting part of the assembler-driven display
definitions. Updated 64tass+cc65 to use ".byte" as their dense hex
pseudo-op, and to use the updated formatter code. No changes to
regression test output.
(Changes were requested in issue #42.)
Also, added a resize gripper to the bottom-right corner of the main
window. (These seem to have generally fallen out of favor, but I
like having it there.)
- Show the full path in the tooltip for the two "recent project"
buttons shown on the launch panel.
- Reset the app title bar and status bar contents when the project
is closed.
Added comments, renamed files, removed cruft.
Stop showing the visualization tag name in the code list. It's
often redundant with the code label, and it's distracting. (We may
want to make this an option so you can Ctrl+F to find a tag.)
First swing at a visualizer for Atari 2600 sprites and playfields.
Won't necessarily present an accurate view of what is displayed on
screen, but should provide a reasonable shape for data stored in
the obvious way.
The Adventure playfields looked squashed, so I added a simple row
duplication value.
Also, minor improvements to visualizers generally:
- Throw an exception, rather than an Assert, in VisBitmap8 when the
arguments are bad.
- Show the exception in the Visualization Edit dialog.
- If generation fails and we don't have an error message, show a
generic "stuff be broke" string.
- Set focus on OK button in Visualization Set Edit after editing,
so you can hit Enter twice after renaming a tag.
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.
Report visualization generation errors through an explicit
IApplication interface, instead of pulling messages out of the
DebugLog stream.
Declare that GetVisGenDescrs() is only called when the plugin is in
the "prepared" state, so that plugins can taylor the set based on
the contents of the file. (This could be used to set min/max on
the "offset" entries, but I want special handling for offsets, so
we might as well set it later.)
Bitmap fonts are a series of (usually) 1x8 bitmaps, which we arrange
into a grid of cells.
Screen images are useful for embedded screens, or for people who want
to display stand-alone image files as disassembly projects.
Various improvements:
- Switched to ReadOnlyDictionary in Visualization to make it clear
that the parameter dictionary should not be modified.
- Added a warning to the Visualization Set editor that appears when
there are no plugins that implement a visualizer.
- Make sure an item is selected in the set editor after edit/remove.
- Replaced the checkerboard background with one that's a little bit
more grey, so it's more distinct from white pixel data.
- Added a new Apple II hi-res color converter whose output more
closely matches KEGS and AppleWin RGB.
- Added VisHiRes.cs to some Apple II system definitions.
- Added some test bitmaps for Apple II hi-res to the test directory.
(These are not part of an automated test.)
Thumbnails are now visible in the main list and in the visualization
set editor. They're generated on first need, and regenerated when
the set of plugins changes.
Added a checkerboard background for the visualization editor bitmap
preview. (It looks all official now.)
The Visualization and Visualization Set editors are now fully
functional. You can create, edit, and rearrange sets, and they're
now stored in the project file.
Implemented Apple II hi-res bitmap conversion. Supports B&W and
color. Uses essentially the same algorithm as CiderPress.
Experimented with displaying non-text items in ListView. I assumed
it would work, since it's the sort of thing WPF is designed to do,
but it's always wise to approach with caution. Visualization Sets
now show a 64x64 button as a placeholder for the eventual thumbnail.
Some things were being flaky, which turned out to be because I
wasn't Prepare()ing the plugins before using them from Edit
Visualization. To make this a deterministic failure I added an
Unprepare() call that tells the plugin that we're all done.
NOTE: this breaks all existing plugins.
Added some rudimentary bitmap creation code. Got a test pattern
generated by the plugin to display in the app. (Most of the time
required for this was spent figuring out how bitmaps are handled
in WPF.)
Got parameter in/out working in EditVisualization dialog. Did some
rearranging in PluginCommon interfaces and data structures. Still
doesn't do anything useful.
Basic infrastructure for taking a list of parameters from a plugin
and turning it into a collection of UI controls, merging in values
from a Visualization object. Doesn't yet do anything useful.
WPF makes the hard things easy and the easy things hard. This was
a hard thing, so it was easy to do (with some helpful sample code).
Yay WPF?
It's pretty common for code to access BUFFER-1,X, but it's rare for
the buffer to live on zero page memory. More often than not we're
auto-formatting zero-page operands with a nearby symbol when they're
just simple variables. It's more confusing than useful, so we don't
do that anymore.
Updated documentation for non-unique label changes. Added a new
section to tutorial #1.
Updated examples to use non-unique labels and variable tables.
Tweaked the EditLabel radio button names.
Correct handling of local variables. We now correctly uniquify them
with regard to non-unique labels. Because local vars can effectively
have global scope we mostly want to treat them as global, but they're
uniquified relative to other globals very late in the process, so we
can't just throw them in the symbol table and be done. Fortunately
local variables exist in a separate namespace, so we just need to
uniquify the variables relative to the post-localization symbol table.
In other words, we take the symbol table, apply the label map, and
rename any variable that clashes.
This also fixes an older problem where we weren't masking the
leading '_' on variable labels when generating 64tass output.
The code list now makes non-unique labels obvious, but you can't tell
the difference between unique global and unique local. What's more,
the default type value in Edit Label is now adjusted to Global for
unique locals that were auto-generated. To make it a bit easier to
figure out what's what, the Info panel now has a "label type" line
that reports the type.
The 2023-non-unique-labels test had some additional tests added to
exercise conflicts with local variables. The 2019-local-variables
test output changed slightly because the de-duplicated variable
naming convention was simplified.
Implemented assembly source generation of non-unique local labels.
The new 2023-non-unique-labels test exercises various edge cases
(though we're still missing local variable interaction).
The format of uniquified labels changed slightly, so the expected
output of 2012-label-localizer needed to be updated.
This changes the "no opcode mnemonics" and "mask leading underscores"
functions into integrated parts of the label localization process.
The label localizer is now always on. The regression tests turned
it off by default, but that's no longer allowed, so the generated
output has changed for many of them. The tests themselves were not
altered.
Update the symbol lookup in EditInstructionOperand, EditDataOperand,
and GotoBox to correctly deal with non-unique labels.
This is a little awkward because we're doing lookups by name on
a non-unique symbol, and must resolve the ambiguity. In the case of
an instruction operand that refers to an address this is pretty
straightforward. For partial bytes (LDA #>:foo) or data directives
(.DD1 :foo) we have to take a guess. We can probably make a more
informed guess than we currently are, e.g. the LDA case could find
the label that minimizes the adjustment, but I don't want to sink a
lot of time into this until I'm sure it'll be useful.
Data operands with multiple regions are something of a challenge,
but I'm not sure specifying a single symbol for multiple locations
is important.
The "goto" box just finds the match that's closest to the selection.
Unlike "find", it always grabs the closest, not the next one forward.
(Not sure if this is useful or confusing.)
Added serialization of non-unique labels to project files.
The address labels are stored without the non-unique tag, because we
can get that from the file offset. (If we stored it, we'd need to
extract the value and verify that it matches the offset.) Operand
weak references are symbolic, and so do include the tag string.
We weren't validating symbol labels before. Now we are.
This also adds a "NonU" filter to the Symbols window so the labels
can be shown or hidden as desired.
Also, added source for a first pass at a regression test.
- Renamed "strip label prefix/suffix" to "omit label prefix/suffix".
- Changed a Merlin operand workaround so it doesn't apply to code
that is explicitly not in bank zero.
- Changed {addr}/{const} annotations on project/platform symbol
equates so they line up a little better on screen and in exported
sources.
Continue development of non-unique labels. The actual labels are
still unique, because we append a uniquifier tag, which gets added
and removed behind the scenes. We're currently using the six-digit
hex file offset because this is only used for internal address
symbols.
The label editor and most of the formatters have been updated. We
can't yet assemble code that includes non-unique labels, but older
stuff hasn't been broken.
This removes the "disable label localization" property, since that's
fundamentally incompatible with what we're doing, and adds a non-
unique label prefix setting so you can put '@' or ':' in front of
your should-be-local labels.
Also, fixed a field name typo.
This adds the concept of label annotations. The primary driver of
the feature is the desire to note that sometimes you know what a
thing is, but sometimes you're just taking an educated guess.
Instead of writing "high_score_maybe", you can now write "high_score?",
which is more compact and consistent. The annotations are stripped
off when generating source code, making them similar to Notes.
I also created a "Generated" annotation for the labels that are
synthesized by the address table formatter, but don't modify the
label for them, because there's not much need to remind the user
that "T1234" was generated by algorithm.
This also lays some of the groundwork for non-unique labels.
If an address map entry wraps around the end of a bank, add a note
to the message log. This is Error level, since some assemblers
will refuse to handle it.
It's too easy to hit Escape after making a bunch of changes, so
now we ask for confirmation.
(Might make sense to make this strictly an Esc guard, and not
pester the user if they actually hit the Cancel button or close
box. I'm not convinced though; Esc+Enter isn't terrible.)
Some style guides say you should only put one space between
sentences, but I and many others still put two. The line-folding
code was only eating one of them when they straddled the end of the
line, which looked a little funny because the following line was
indented by one space.
This tweaks the code to eat both spaces. Regression test updated.
Also, nudge some UI elements so they line up.