The biggest part of that OS deals with the user interface (go figure), specifically the routines for controlling the LCD. The most demanding of the routines have been done for well over a year now, ever since I finished testing the LCD display with the breadboard version of the MAG-85.
The Early MAG-85 with LCD Demo Program
When writing my own software while playing with the LCD (i.e. goofing off rather than writing code for the monitor), I've been writing lots of ad-hoc software to write to the LCD or control it whenever I wanted something more sophisticated than "write this character to the screen" or "send this string to the screen". Character out and string out routines were in my early test software. What I needed were things like automatic wrapping at the end of the displayed line and some terminal control commands.
Coding Rule: Make One to Throw Away
The display controller for the LCD has a larger "display" area than the LCD actually displays. Its buffer holds two lines of 40 characters. That's really nice on my other display which has a 40x2 LCD display on it. But the MAG-85 uses a 16x2 display. This means you can send characters to it, and it'll happily accept them and put them into the buffer in places that the LCD doesn't show. So you don't see over half of what you write. Or you need to keep track of how many characters you've written since the start of the line and wrap to the start of line 2 yourself. And so on.
In my first shot at a set of LCD routines for the system monitor, I wrote a bunch of stand alone cursor position tracking and movement routines. Then I had to invoke them from all over to keep track of stuff. And since the software had to do its own tracking, stuff would get missed, the LCD would get out of sync, and it became standard practice to re-home the cursor and display every so often to keep things from going off track for too long.
Plus the number of routines was getting out of hand, along with the size of the software. I'd intended the software to come in somewhere around a page in length, and I was at about twice that with only about half the software implemented! For comparison sake, a system that uses a hardware approach to display control (e.g. LED or other simple segmented displays with data buffers and select logic) rather than software like the LCD uses fits the whole monitor into about 1K of memory. I was looking at my LCD routines taking up as much room as the whole rest of the monitor.
Frankly, I felt that I was going the wrong way, and it slowed me down in getting the monitor done.
Coding Rule: Make Another to Keep
I decided to strip the code back to my original tight routines. All they do is initialize the LCD, send out a character or a command byte, or a string of characters. First, I dressed up my initialization routine by moving out some recurring code for delays into subroutines. This not only reduced the size of that routine, but made those subroutines available elsewhere.
Then I looked at my character out routine, and decided to put the intelligence about where the cursor was in there. After all, if it gets written this is where it happens. I built in an automatic wrap. It seemed to fit well, and it took a lot of heat off the user code. Suddenly things were looking a lot better.
Once I got to rewriting some of the other added functionality, it turned out smaller and simpler. It went so well, that I'm much farther along in implementing everything I want than I got with the old code. And at present I'm only just over a page in length, without having gone back to look for optimizations (repeated code and so on.) That'll come next, after which I'll be desk=checking my stack handling as I jump around between different routines.
But I'm much happier, and I've got a lot more to show for my time this time. It's nothing revolutionary, but there are times when it's a breakthrough just to step back and see the obvious.