Three sides good, four sides bad.

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.

The Advanced User Guide for the BBC MicroAs 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.

BBC BASIC's improved filling, *EXEC and Lights Out

Thursday, 13th November 2008

Progress on the TI-83+/TI-84+ port of BBC BASIC continues - I'm hoping to get a beta release out soon. smile.gif

2008.11.09.01.gif    2008.11.10.02.gif    2008.11.12.01.gif

I've done quite a lot of work on the graphics features. Every shape that is plotted can be set to either the foreground colour, background colour or to invert the pixels it covers. This wasn't implemented properly (everything was always drawn in the foreground colour) which has been corrected.

The first image in the above group shows the flood-filler in action, filling inside and outside a triangle. The second image demonstrates the ellipse drawing and filling code by qarnos. It had a small amount of overdraw, which is not normally a problem, but in an inverting plot mode drawing a pixel twice causes it to reset to its original value. This ends up leaving gaps in the circle. Fortunately he was able to give me a lot of help in fixing it. smile.gif

The third image demonstrates a non-standard feature I've added - being able to set your own fill patterns. The GCOL statement lets you set the foreground or background colour, and for values between black and white a dithered fill pattern is substituted instead. GCOLPAT takes a pointer to an 8×8 pixel fill pattern and subsequent fill operations will use that instead; passing FALSE (0) to GCOLPAT or setting a colour normally via GCOL reverts to the standard dither fills.

I've also done a small amount of benchmarking. There's a sample program in the TI-83+ guidebook that draws a Sierpinski triangle.


On a regular 6MHz TI-83+, the TI program takes 7 minutes and 8 seconds to run. A direct translation to BBC BASIC executes in 2 minutes and 21 seconds, and a simplified version executes in 1 minute and 56 seconds.


I'm also trying to improve the number of OS-level "star" commands. Above is a demonstration of *EXEC which reads console input from a text file. A file is opened for output using OPENOUT, some text is written into it using PRINT#, and then it it *EXECuted. This is one possible way of converting a text file into a BBC BASIC program.


Finally, I'm trying to write a game as an example program. The above screenshot shows an incomplete clone of the Lights Out game by Tiger Electronics.

FirstOctober 2008December 2008Last RSSSearchBrowse by dateIndexTags