2023-03-19
This week several developments occurred.
These changes, which are only done for the TSR example as yet but can be ported to the other TSRs (RxANSI, lClock, SEEKEXT, KEEPHOOK, TESTALOC), concern the detection of a debugger as well as a resident instance of the application. It's important to optimise these because in the common case, nearly 256 multiplex numbers need to be checked. Tracing lClock on the HP 95LX took very long because of these loops.
First I cut down on the number of instructions running per check. I inlined the debugger check to avoid the overhead of a call. For the resident instance check, I changed the call protocol of the check function so it won't return on finding an instance, cutting down on the signalling and the conditional branches after the calls. (Inlining this check is not possible because the /X=
number needs to be checked before running the loop from 0FFh to 00h, in case it is set.)
Next, I changed the ''.loopplex'' loop in the interrupt unhook handler so as to push and pop cx
once each, rather than for every multiplex number.
Finally, I re-arranged things so that there is only a single loop which checks for both the debugger and the resident instance, calling the AMIS installation check only once per multiplex number. If one of the two is found, the loop continues to search only for the other. If the other is subsequently found as well, then the loop is aborted. This nearly halves the number of instructions in the worst case and adds about 20 instructions in the best case (if the debugger and the resident instance are both immediately found).
There is a slight behaviour change: If an /X=
number is specified then this first check will now also check for the debugger. This is considered acceptable.
First I extracted most of the IOCLINE
logic into three separate functions to make it usable for other callers. The first such caller is the Rx.LIST
command. It was first converted to buffer data in the line_out
buffer, flushing this buffer if it gets too full or at the very end. Then it was changed to use the new functions.
Next, the original IOCLINE
logic was replaced by three function calls to the new functions, significantly cleaning up this bit and making it easier to grasp. This was helped a lot by how generic the new functions turned out to be, almost completely eliminating the special-casing of the prompt string followed by the input string. I think it's a big win for readability.
The next changes were done in the function formerly known as rawinput
, now renamed ''getinput''. These changes were ported from lDebug back to the ''getinput'' function of TracList, which is written in perl. The TracList application originated the more complex ''getinput'' logic which redraws within a single row to allow entering and editing lines longer than would fit in the amount of columns per line.
The changes include several bugfixes for very narrow display columns, such as comparing the col
variable to maxpercol
when it should be compared to the sum of maxpercol
and promptlength
. The next fix was forcing ''maxpercolhalf'' to 1 if it was calculated as 0, avoiding an infinite loop.
The final fix concerns handling of narrow lines as well; in the test case there is a maxpercol
of 5 and thus maxpercolhalf
of 2. When entering the string ";456789abcdef" then scrolling back using the Left Arrow key, the letter "a" will not become visible. This was fixed by checking if scrolling back results in a cursor column (col
) at the very end of the visible window, and there would be an invisible text codepoint just off the visible part (ie, we aren't displaying the very end of the input already).
The next change is simply to make the register change highlighting conditional on a build time option. This was in preparation to a new option which highlights the first and last visible text codepoint of the getinput
line if there is more (currently invisible) text past the first/last text.
Finally, some optimisations were made, one of which is somewhat important for Einsicht: If a text codepoint is appended to the input line without scrolling the visible text, then only the appended text is displayed in place now. This avoids the prior behaviour of redrawing the entire prompt and input so far for every appended codepoint. The other optimisation concerns handling of the Left Arrow and Right Arrow keys; if they result in the cursor scrolling without scrolling the visible input text, then only the text in front of the desired cursor position is redrawn. Previously this would redraw the entire visible text and then also the text in front of the target cursor position. (Idea: If we are scrolling the cursor to the right then it may suffice to display only a single codepoint. This may require highlighting if the cursor was in the very left-most visible spot.)
Both of these optimisations mandated moving the first redraw of the prompt later into the getinput
redraw handler, just before the full input text is redrawn. This is to make it conditional on the append and cursor move conditions both being false. The conditions are, in turn, both forced to false in case the lastskip
value does not match the new skip
variable (held in register di
). So the conditions must be checked, to avoid the prompt redraw, after the final value of skip
has been determined.
A small optimisation changes the boolean variables, stored one per byte, in getinput
to use -1 as the true value. This allows to check them using rol
and invert them using not
, for shorter instruction encodings. This optimisation is gleaned from shsucdx. A related optimisation is to share code pathes that set a single flag before jumping back to the main processing loop.
Today I noted that andrewbird suggested a Pull Request to FreeDOS SHARE that is said to require a bugfix in the toolchain. To avoid a broken build of my automatic daily builds, if this PR is merged, I went and rebuilt the toolchain on our servers. I found three defects during that:
-E exit
command passed to it by the libi86 test suite to check for COM4 support, resulting in a hang.
Also, some of the libi86 tests failed, but I was able to ignore that by running (cd build-libi86 && make install)
to force installation.
Another problem was the server storage space, which is close to filling the 212 GB allocated to it.
Discussion
Just a quick note to say that the bugfix to the ia16-gcc toolchain was only relevant if you used the -mtsr option. Here's the commit msg https://github.com/tkchia/newlib-ia16/commit/03a53fa3090b98941a5d2cf88c77e8ce4110cbef
That option is used for FD Share though, correct?
Yes, sure is. I'm not sure it had any effect beforehand as I only saw evidence when adding the kitten support. Certainly prudent to rebuild, I just wanted others to know that the issue only affected programs built with the -mtsr option. As far as I know, I'm the only user of it in the FreeDOS ecosystem so far.
Thanks.