This is another attempt to fix the ListView keyboard position
behavior. Basic problem: if you change something in the ListView,
the keyboard position is lost, and WPF doesn't expose a nice way to
save and restore it. It appears the way to set the position is by
calling Focus() on the specific item you want to have as the "current"
keyboard position, but you can only do that at certain times.
This attempt removes the grid-splitter resize hack, in favor of just
setting a "needs refocus" flag when we restore the selection set.
This causes Focus() to be called from the StatusChanged callback on
the next event with status="containers generated".
During testing I noticed some other odd behavior: if you used "goto"
to jump to an address, up/down arrows would change focus to a
different control (menu items, grid splitters, etc). The problem
there was that we were setting focus to the ListView control rather
than to a ListViewItem, so arrow keys were in control-traversal mode
rather than list-walk mode. That is also fixed.
(Issue #105)
The DCI string format uses character values where the high bit of the
last byte differs from the rest of the string. Usually all the high
bits are clear except on the last byte, but SourceGen generally allows
either polarity.
This gets a little uncertain with single-character strings, because
SourceGen can't auto-detect DCI very effectively. A series of bytes
with the high bit set could be a single high-ASCII string or a series
of single-byte DCI strings.
The motivation for allowing them is C64 PETSCII. While ASCII allows
"high ASCII" as an escape hatch, PETSCII doesn't have that option, so
there's no way to mark the data as a character or a string. We still
want to do a bit of screening, but if the user specifies a non-ASCII
character set and the selected bytes have their high bits set, we
want to just treat the whole set as 1-byte DCI.
Some minor adjustments were needed for a couple of validity checks
that expected longer strings.
This adds some short DCI strings in different character sets to the
char-encoding regression tests.
(for issue #102)
The code for formatting an address table allows you to specify that
code start tags should be placed on all targets. However, unnecessary
tags are undesirable, and it's not necessary to add a tag if the
target is already treated as executable code. So the implementation
tested to see if the target address was already an instruction.
The code was incorrectly testing for "is instruction", rather than "is
instruction start", which meant that if the table entry pointed at an
instruction embedded inside another instruction we would conclude that
the tag wasn't necessary, when in fact it was. Not only weren't we
getting a useful table entry, we were adding a symbolic reference to a
hidden label.
(issue #103)
When formatting one or more strings with the Edit Data Operand dialog,
the code must determine which options to present. If the selected
bytes appear to represent one or more null-terminated strings, that
option is enabled in the UI.
The "format recognizers" enforce some strict rules, e.g. null-
terminated strings must end in $00, and also try to confirm that the
data looks like a printable string. The algorithm rejects strings
with "illegal" characters in them. This is simpler on some systems
than others. For example, C64 PETSCII defines quite a few control
characters in ways that make them useful for embedding in printable
strings.
The "recognizers" are only used by the operand edit feature, not as
part of an automated string detector, so there's no real upside in
overriding the user's desire to form a string with arbitrary bytes.
This removes the quick rejection from the four recognizers (null-term,
len8, len16, dci). It does not alter the high-level code, which
still insists on a certain percentage of the string being printable;
that may be worth revisiting as well.
(issue #100)
64tass wants to place its output into a 64KB region of memory,
starting at the address "*" is set to, and continuing without
wrapping around the end of the bank. Some files aren't meant to be
handled that way, so we need to generate the output differently.
If the file's output fits nicely, it's considered "loadable", and
is generated in the usual way. If it doesn't, it's treated as
"streamable", and the initial "* = addr" directive is omitted
(leaving "*" at zero), and we go straight to ".logical" directives.
65816 code with an initial address outside bank 0 is treated as
"streamable" whether or not the contents fit nicely in the designated
64K area. This caused a minor change to a few of the 65816 tests.
A new test, 20240-large-overlay, exercises "streamable" by creating
a file with eight overlapping 8KB segments that load at $8000.
While the file as a whole fits in 64KB, it wouldn't if loaded at
the desired start address.
Also, updated the regression test harness to report assembler
failure independently of overall test failure. This makes it easier
to confirm that (say) ACME v0.96.4 still works with the code we
generate, even though it doesn't match the expected output (which
was generated for v0.97).
(problem was raised in issue #98)
The initial implementation was testing the byte value rather than
the converted value, so backslashes were getting through in high
ASCII strings. PETSCII and C64 screen codes don't really have a
backslash so it's not really an issue there.
The new implementation handles high ASCII correctly. The various
201n0-char-encoding-x regression tests have been updated to verify
this.
The code generator outputs an optional comment specifying which
version of which assembler the code was generated for. This was
handled inconsistently and, for the most part, incorrectly. We now
report the correct version.
Two things changed: (1) string literals can now hold backslash
escapes like "\n"; (2) MVN/MVP operands can now be prefixed with '#'.
The former was a breaking change because any string with "\" must
be changed to "\\". This is now handled by the string operand
formatter.
Also, improved test harness output. Show the assembler versions at
the end, and include assembler failure messages in the collected
output.
If you have multiple overlapping segments (say, four 8KB chunks
that all load at $8000), and you use the "goto" command to jump
to address $8100, it should try to jump to that address within
whichever segment you happen to be working (based on the current
line selection). If that address doesn't exist in the current
segment, it's okay to punt and jump to the first occurrence of that
address in the file.
The existing code was always jumping to the first instance.
(related to issue #98)
Code generated by one of the C compilers sets up the stack frame and
then maps the direct page on top of it. If the value at the top of
the stack is 16 bits, it will be referenced via address $ff. The
local variable editor was regarding this as illegal, because lvars are
currently only defined for direct page data, and the value doesn't
entirely fit there (unless you're doing an indirect JMP on an NMOS
6502, in which case it wraps around to $00... but let's ignore that).
The actual max width of a local variable is 257 because of the
possibility of a 16-bit access at $ff.
Older versions of SourceGen don't seem to have an issue when they
encounter this situation, as worrying about (start+width) is really
just an editor affectation. The access itself is still a direct-page
operation. You won't be able to edit the entry without reducing the
length, but otherwise everything works. I don't think there's a need
to bump the file version.
Added a compiled C implementation of strlen(). The most interesting
part about this is that it references a 16-bit value via direct-page
address $ff, which means you'd want a local variable with
address=$ff and width=2. The current UI prevents this.
Renamed from "*-incl.html" to "incl-*.html" so they sort together.
Moved <div> for all but incl-head inside include file.
Overall this shouldn't do anything but move the magic comments around
inside the HTML files.
We were using a very simple regex pattern for the label part, and
not performing additional validation checks later. This allowed
a symbol that started with a number (e.g. "4ALL") to get much farther
than it should have.
This change modifies the regex pattern to match only valid label
syntax.
Doesn't really affect the pages on the web, but it's easier to
preview them in the filesystem when linked to "../main.css" rather
than "/main.css".
The common portion of the <head> section is now in a separate
"include" file.
Added some indentation to masthead/topnav/sidenav so it looks nicer
in the merged source listing.
The idea is to remove everything but the "HOME" link from the topnav
bar on very narrow devices, so that it doesn't look cramped. Right
now we don't have a ton of stuff in topnav, and losing the tutorial
link is annoying.
If we want to restore this feature, we should also add a link to the
tutorial in the body of the page.
A bit of Javascript was used to remove the hamburger icon when a
page doesn't have a #sidenav. This worked when sidenav-incl was
being loaded with jQuery load(), because that mechanism works
asynchronously, and #sidenav was part of the DOM before it ran.
Once we started merging HTML fragments directly into the pages, the
script got called before #sidenav was defined, so the icon was
always being removed.
One solution would be to move the script to footer-incl.html, to
follow the preferred practice of placing scripts at the bottom of
the <body>. The better solution was to move the "no-sidenav" class
from #main to <body>, so that all components can see it. This lets
us use CSS rules to hide the icon.
Replaced the link at the top of the manual. Remove reference to
old tutorial doc. Added an obsolescence notice to the top of the
old tutorial. Updated tutorial message and link in README.
Also, fixed sidenav style.
This change applies the substitution scripts on the HTML files,
replacing away the jQuery load() calls with the actual file contents,
and setting the correct URLs to the prev/next buttons.
This isn't currently needed anywhere else, so the list of filenames
is just hard-coded into the script. Instead of making substitutions
in the source data, this just generates the full data.
Fairly straightfoward in Python.
Also, fixed the sidenav references, which should be using the file
in the sgtutorial subdirectory.
Also, tweaked index.html a bit.
Added a SourceGen tutorial with lots of screen shots. Uses
"responsive web design" so it works well on mobile devices.
This version is using jQuery load() calls to pull in pieces, but
that causes a lot of blink when loading because the loads are
asynchronous and may not complete until after the initial page
render has finished.
Tutorial prev/next links not yet working.