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.
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.)
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.
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.
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.
Sometimes there's a bunch of junk in the binary that isn't used for
anything. Often it's there to make things line up at the start of
a page boundary.
This adds a ".junk" directive that tells the disassembler that it
can safely disregard the contents of a region. If the region ends
on a power-of-two boundary, an alignment value can be specified.
The assembly source generators will output an alignment directive
when possible, a .fill directive when appropriate, and a .dense
directive when all else fails. Because we're required to regenerate
the original data file, it's not always possible to avoid generating
a hex dump.
Memory-mapped I/O locations can have different behavior when read
vs. written. This is part 1 of a change to allow two different
symbols to represent the same address, based on I/O direction.
This also adds a set of address masks for systems like the Atari
2600 that map hardware addresses to multiple locations.
This change updates the data structures, .sym65 file reader,
project serialization, and DefSymbol editor.
Early data sheets listed BRK as one byte, but RTI after a BRK skips
the following byte, effectively making BRK a 2-byte instruction.
Sometimes, such as when diassembling Apple /// SOS code, it's handy
to treat it that way explicitly.
This change makes two-byte BRKs optional, controlled by a checkbox
in the project settings. In the system definitions it defaults to
true for Apple ///, false for all others.
ACME doesn't allow BRK to have an arg, and cc65 only allows it for
65816 code (?), so it's emitted as a hex blob for those assemblers.
Anyone wishing to target those assemblers should stick to 1-byte mode.
Extension scripts have to switch between formatting one byte of
inline data and formatting an instruction with a one-byte operand.
A helper function has been added to the plugin Util class.
To get some regression test coverage, 2022-extension-scripts has
been configured to use two-byte BRK.
Also, added/corrected some SOS constants.
See also issue #44.
The ability to give explicit widths to local variables worked out
pretty well, so we're going to try adding the same thing to project
and platform symbols.
The first step is to allow widths to be specified in platform files,
and set with the project symbol editor. The DefSymbol editor is
also used for local variables, so a bit of dancing is required.
For platform/project symbols the width is optional, and is totally
ignored for constants. (For variables, constants are used for the
StackRel args, so the width is meaningful and required.)
We also now show the symbol's type (address or constant) and width
in the listing. This gets really distracting when overused, so we
only show it when the width is explicitly set. The default width
is 1, which most things will be, so users can make an aesthetic
choice there. (The place where widths make very little sense is when
the symbol represents a code entry point, rather than a data item.)
The maximum width of a local variable is now 256, but it's not
allowed to overlap with other variables or run of the end of the
direct page. The maximum width of a platform/project symbol is
65536, with bank-wrap behavior TBD.
The local variable table editor now refers to stack-relative
constants as such, rather than simply "constant", to make it clear
that it's not just defining an 8-bit constant.
Widths have been added to a handful of Apple II platform defs.
Variables are now handled properly end-to-end, except for label
uniquification. So cc65 and ACME can't yet handle a file that
redefines a local variable.
This required a bunch of plumbing, but I think it came out okay.
We now generate FormatDescriptors with WeakSymbolRefs for direct
page references that match variable table entries.
LocalVariableTable got a rewrite. We need to be unique in both
name and address, but for the address we have to take the width into
account as well. We also want to sort the display by address
rather than name. (Some people might want it sorted by name, but
we can worry about that some other time.)
Updated the DefSymbol editor to require value uniqueness. Note
addresses and constants exist in separate namespaces.
The various symbols are added to the SymbolTable so that uniqueness
checks work correctly. This also allows the operand generation to
appear to work, but it doesn't yet handle redefinition of symbols.
This involved adding a list to the DisasmProject, creating a new
UndoableChange type, and writing the project file serialization
code. While doing the latter I realized that the new Width field
was redundant with the FormatDescriptor Length field, and removed it.
I added a placeholder line type, but we're not yet showing the
table in the display list. (To edit the tables you just have to
know where they are.)
It's not quite the same as the character encoding -- sometimes we
want a mix of things -- so it gets its own enum. The value is
saved to the project file, but not actually used yet.
Also, moved some combo box strings into XAML resources.
The previous code output a character in single-quotes if it was
standard ASCII, double-quotes if high ASCII, or hex if it was neither
of those. If a flag was set, high ASCII would also be output as
hex.
The new system takes the character value and an encoding identifier.
The identifier selects the character converter and delimiter
pattern, and puts the two together to generate the operand.
While doing this I realized that I could trivially support high
ASCII character arguments in all assemblers by setting the delimiter
pattern to "'#' | $80".
In FormatDescriptor, I had previously renamed the "Ascii" sub-type
"LowAscii" so it wouldn't be confused, but I dislike filling the
project file with "LowAscii" when "Ascii" is more accurate and less
confusing. So I switched it back, and we now check the project
file version number when deciding what to do with an ASCII item.
The CharEncoding tests/converters were also renamed.
Moved the default delimiter patterns to the string table.
Widened the delimiter pattern input fields slightly. Added a read-
only TextBox with assorted non-typewriter quotes and things so
people have something to copy text from.
We've been treating ASCII strings and instruction/data operands as
ambiguous, resolving low vs. high when generating output for the
display or assembler. This change splits it into two separate
formats, simplifying output generation.
The UI will continue to treat low/high ASCII as as single thing,
selecting the format appropriately based on the data. There's no
reason to have two radio buttons that are never both enabled.
The data operand string functions need some additional work, but
that overlaps substantially with the upcoming PETSCII changes, so
for now all strings set by the data operand editor are low ASCII.
The file format has changed again, but since there hasn't been a
release since the previous change, I'm leaving the file format
at v2. Code has been added to resolve the ASCII mode when loading
a v1 project file.
This removes some complexity from the assembly code generators.
This was the result of the earlier change to eliminate "reverse DCI"
strings. On further examination, it doesn't seem like we can do
much better than a hex dump without more work than the situation
merits. So hex dump it is.
We used to use type="String", with the sub-type indicating whether
the string was null-terminated, prefixed with a length, or whatever.
This didn't leave much room for specifying a character encoding,
which is orthogonal to the sub-type.
What we actually want is to have the type specify the string type,
and then have the sub-type determine the character encoding. These
sub-types can also be used with the Numeric type to specify the
encoding of character operands.
This change updates the enum definitions and the various bits of
code that use them, but does not add any code for working with
non-ASCII character encodings.
The project file version number was incremented to 2, since the new
FormatDescriptor serialization is mildly incompatible with the old.
(Won't explode, but it'll post a complaint and ignore the stuff
it doesn't recognize.)
While I was at it, I finished removing DciReverse. It's still part
of the 2005-string-types regression test, which currently fails
because the generated source doesn't match.
SourceGen creates "auto" labels when it finds a reference to an
address that doesn't have a label associated with it. The label for
address $1234 would be "L1234". This change allows the project to
specify alternative label naming conventions, annotating them with
information from the cross-reference data. For example, a subroutine
entry point (i.e. the target of a JSR) would be "S_1234". (The
underscore was added to avoid confusion when an annotation letter
is the same as a hex digit.)
Also, tweaked the way the preferred clipboard line format is stored
in the settings file (was an integer, now an enumeration string).