Sunday, 30th November 2008
Work on the TI-83+/TI-84+ port of BBC BASIC continues bit-by-bit.
I've added triangle filling (left) and, by extension, parallelogram filling (right) PLOT commands. The triangle filler is a little sluggish, tracing each edge of the triangle using 16-bit arithmetic, but it seems fairly robust. I am trying to focus on robustness over speed for the moment, but it would seem easy enough to add a special-case triangle edge tracer if both ends of the edge can fit into 8-bit coordinates (all inputs to plot commands use 16-bit coordinates).
The parallelogram on the right is specified with three coordinates, and the fourth point's position is calculated with point3-point2+point1. As parallelograms are drawn as two triangles there's an overdraw bug when they are drawn in an inverting plotting mode.
This needs to be fixed.
The BBC Micro OS exposed certain routines in the &FF80..&FFFF address range. These routines carried out a wide variety of tasks, from outputting a byte to the VDU to reading a line of input or changing the keyboard's auto-repeat rate. BBC BASIC (Z80) lets the person implementing the host interface catch these special-case calls, so I've started adding support for them. A friend very kindly donated copies of three BBC Micro books, including the advanced user guide (documenting, amongst other things, the OS routines) and the BASIC ROM manual.
As an example, if you write the value 16 to the VDU it clears the text viewport. BBC BASIC has the CLS keyword for this, but you can also send values directly to the VDU with the VDU statement, like this: VDU 16. This in turn calls the BBC Micro's OSWRCH routine, located at &FFEE, with the accumulator A containing the value to send to the VDU. An alternative method to clear the text viewport would therefore be A%=16:CALL &FFEE.
Now, you may well be wondering how this is of any use, given the existance of a perfectly good CLS statement (or, failing that, the VDU statement). The usefulness becomes apparent when you remember that BBC BASIC has an inline assembler. There is no CLS or VDU instruction in Z80 assembly, but by providing an OSWRCH routine you can interact with the host interface and so clear the screen from an assembly code routine; in this case [LD A,16:CALL &FFEE:] (square brackets delimit assembly code).
Sadly, there is a limitiation in the TI-83+/TI-84+ hardware that prevents this from working seamlessly. The memory in the range &C000..&FFFF, where these routines reside, is mapped to RAM page 0. RAM page 0 has a form of execution protection applied to it, so if the Z80's program counter wanders onto RAM page 0 the hardware triggers a Z80 reset. To this end all of these OS calls are relocated to &4080..&40FF, so in the Z80 assembly snippet above you would CALL &40EE instead. This only applies to CALLs made from assembly code - the BASIC CALL statement traps calls to the &FF80..&FFFF so they can be redirected seamlessly to retain compatibility with other versions of BBC BASIC (Z80).
After all this work I noticed that the host interface was crashing in certain situations, especially when writing to a variable-sized file in a loop. This is the sort of bug that is tricky to fix; sometimes it would crash instantly, sometimes it would write the first 5KB of the file fine then crash.
It turned out to be a bug in the interrupt service routine (ISR). In this application the ISR is used to handle a number of tasks such as trapping the On key being pressed to set the Escape condition or to increment the TIME counter (as well as other time-related features such as the keyboard auto-repeat or cursor flash). On the TI-83+, which doesn't have a real-time clock, it also calls a RTC.Tick function approximately once per second to update the (very inaccurate) software real-time clock. To call this function it uses the BCALL OS routine. It appears that if the BCALL routine was used from an ISR when the TI-OS was in the process of enlarging a file it would crash. Removing the call to RTC.Tick appears to have fixed the bug entirely.
It is possible to put BBC BASIC into an infinite loop if you make a mistake in your error handler. In the above example program the error handler in line 10 fails to bail out on an error condition, running back into line 20 that itself triggers a division by zero error. You cannot break out of the loop by pressing On as that works by triggering an error (error 17, Escape). To improve safety I've added a feature whereby holding the On key down for about 5 seconds causes BBC BASIC to restart. This loses the program that was previously loaded in RAM, but you can retrieve with the OLD statement.
I've also rewritten all of the "star" commands. These are commands, usually prefixed with an asterisk, that are intended to be passed to the OS. As the TI-83+/TI-84+ does not have an especially useful command-line driven interface (most of the UI is menu-driven) I've implemented this part myself, basing its commands on ones provided by the BBC Micro OS. For example, *SAVE can be used to save a block of memory to a file, or *CAT (aliased to *DIR and *.) can be used to show a list of files.
In the case of *CAT I've added a pattern-matching feature that lets you use ? and * as wildcards to limit the files shown.
After noticing that *COPY took three seconds to copy an 860 byte file I optimised some of the file routines to handle block operations more efficiently. Reading and writing single bytes at a time is still rather sluggish, but I'm not sure that there's much I can really do about that.
Finally, for a bit of fun I noticed a forum post enquiring about writing assembly programs on the calculator. Here's a program that assembles a regular Ion program using BBC BASIC's assembler.