The Absolute Indirect and Absolute Indirect Long addressing modes
(e.g. "JMP (addr)" and "JMP [addr]") are 16-bit values in bank 0.
The code analyzer was placing them in the program bank, which
meant the wrong symbol was being used.
Also, tweak some docs.
This was a relatively lightweight change to confirm the usefulness
of relocation data. The results were very positive.
The relatively superficial integration of the data into the data
analysis process causes some problems, e.g. the cross-reference table
entries show an offset because the code analyzer's computed operand
offset doesn't match the value of the label. The feature should be
considered experimental
The feature can be enabled or disabled with a project property. The
results were sufficiently useful and non-annoying to make the setting
enabled by default.
JSR/JSL calls with inline data have the option of reporting that
they don't continue, which causes the code analyzer to treat them
as JMPs instead. There was a bug that was causing the no-continue
flag to be lost in certain circumstances.
The code now explicitly records the plugin's response in an Anattrib
flag. Test 2022-extension-scripts has been updated with a test case
that exercises this situation.
These were being overlooked because they didn't actually cause
anything to happen (a no-op .ORG sets the address to what it would
already have been). The assembly source generator works in a way
that causes them to be skipped, so everybody was happy.
This seemed like the sort of thing that was likely to cause problems
down the road, however, so we now split regions correctly when a
no-op .ORG is encountered. This affects the uncategorized data
analyzer and selection grouping.
This changed the behavior of the 2004-numeric-types test, which was
visibly weird in the UI but generated correct output.
Added the 2024-ui-edge-cases test to provide a place to exercise
edge cases when testing the UI by hand. It has some value for the
automated regression test, so it's included there.
Also, changed the AddressMapEntry objects to be immutable. This
is handy when passing lists of them around.
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.)
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.
This began with a change to support "BRK <operand>" in cc65. The
assembler only supports this for 65816 projects, so we detect that
and enable it when available.
While fiddling with some test code an assertion fired. This
revealed a minor issue in the code analyzer: when overwriting inline
data with instructions, we weren't resetting the format descriptor.
The code that exercises it, which requires two-byte BRKs and an
inline BRK handler in an extension script, has been added to test
2022-extension-scripts.
The new regression test revealed a flaw in the 64tass code
generator's character encoding scanner that caused it to hang.
Fixed.
Sort of silly to have every handler immediately pull the operand out
of the file data. (This is arguably less efficient, since we now
have to serialize the argument across the AppDomain boundary, but
we should be okay spending a few extra nanoseconds here.)
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.
If we have a bug, or somebody edits the project file manually, we
can end up with a very wrong string, such as a null-terminated
string that isn't, or a DCI string that has a mix of high and low
ASCII from start to finish. We now check all incoming strings for
validity, and discard any that fail the test. The verification
code is shared with the extension script inline data formatter.
Also, added a comment to an F8-ROM symbol I stumbled over.
Extension scripts (a/k/a "plugins") can now apply any data format
supported by FormatDescriptor to inline data. In particular, it can
now handle variable-length inline strings. The code analyzer
verifies the string structure (e.g. null-terminated strings have
exactly one null byte, at the very end).
Added PluginException to carry an exception back to the plugin code,
for occasions when they're doing something so wrong that we just
want to smack them.
Added test 2022-extension-scripts to exercise the feature.
If you set things up just right, it's possible for flag status
changes to fail to get merged.
Added a regression test to 1003-flags-and-branches.
Also, tweaked the instruction operand editor to be a bit smoother
from the keyboard: added alt-key shortcuts, and put the focus on the
OK button after creating/editing a label so you can just hit the
return key twice.
The plugin objects are MarshalByRefObject stubs, which means they
don't actually implement the interfaces we're checking for. There's
some additional overhead to do the interface check. We can avoid
it by doing the interface queries during initialization, and just
checking some bit flags later on.
Also, in the extension script info window, show a list of
implemented interfaces.
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.
The 65816 definition makes it a two-byte instruction, like COP. On
the 6502 it acted like a two-byte instruction, but in practice very
few assemblers treat it that way. Very few humans, for that matter.
So it's now treated as a single byte instruction, with the following
byte encoded as a data value.
Instead of providing no-op CheckJsr/CheckJsl, plugins now declare
which calls they support by defining interfaces on the plugin class.
I added a CheckBrk call for code like Apple /// SOS calls, which
use BRK as an OS call mechanism. The formatting doesn't work quite
right yet because I've been treating BRK as a two-byte instruction.
Hardly anything else does, and I think it's time I stopped (but not
in this commit).
Note: THIS BREAKS ALL PLUGINS that use the inline JSR/JSL feature,
which is pretty much all of them.
In the cross-reference table we now indicate whether the reference
source is doing a read, write, read-modify-write, branch, subroutine
call, is just referencing the address, or is part of the data.