After getting a question about the FIG-Forth source I altered to run on MicroDOS, I decided it needs a page of its own.
The question revealed a limitation of the disk I/O code that I wrote. It worked fine with my simulation but not with a real floppy disk controller. The problem was that a FDC will not read multiple sectors across tracks while my do just enough to get by FDC simulation does.
Adding code to UT71 to allow multiple sector reads to span tracks would require space for code that just isn't available. But FIG-Forth is designed to handle different sized disk sectors. Starting with the good old 128 bytes per sector of a 8" single density floppy.
Change the constants B/BUF and B/SCR to reflect the 512 byte size. Then adjust to size of the disk buffer area. That worked well but use revealed a subtle bug.
Understanding this bug requires an explanation of one of the unusual features of FIG-Forth. Buffers always end with a NULL byte. Parsing will find this and match it to a word called 'X' or NULL. This checks to see if the end of a screen has been reached and executes ;S. Or jiggers things so that scanning continues on the next disk block.
Except that way back when (this is in the original listing from FIG) someone used the literal value of 7 rather than "B/SCR 1 -" when performing this check. Which makes it think screens are 4K. An easy fix, mostly.
Adding those 4 bytes resulted in a short branch crossing a page boundary later on in the word S->D which sign extends a single word integer to a double. Looking at that code I realized that it would be easy to replace the two short branches in it with a single long skip.
FIG-Forth isn't three cycle instruction free already so adding this one should be a problem.
With a bit of work I altered FIG-Forth so it can load instead of MicroDOS. This required more changes then I expected:
UT71 looks for a specific sequence of three bytes ("MIC") at a specific location as a check to make sure it loaded MicroDOS from the sectors loaded. So insert those bytes.
UT71 loads those sectors up where MicroDOS wants to run, not where FIG-Forth wants to be. So FIG-Forth needs to relocate itself. It turns out that UT71 does not jump to the start of the loaded data but a little ways in. In a location that isn't used by FIG-Forth. So that gets code to copy the data.
Complicated a little by the starting conditions being slightly different. The program counter is 3 rather than 0. That needs to be fixed of course before jumping to the usual starting point.
For some reason UT71 does some things before starting MicroDOS that make no sense. First is writes a zero to address 910AH (location called ECHOTP in UT71). Why? I don't know or why MicroDOS couldn't handle that. But it mangles FIG-Forth. So I inserted a long skip in the code there to make space for UT71 to poke in its zero.
While writing that zero, UT71 is also putting the address of the MicroDOS copy of the SCRT call and return functions into R4 and R5. Why? Again I have no clue but in this case I do know that MicroDOS does this as well so UT71 needn't have bothered.
There are several ways to fix this: 1) Delete the offending code in UT71. 2) Add SCRT code to FIG-Forth. 3) Repair the damage by putting the addressed of the UT71 routines back in R4 and R5.
I went with option 3.
Which gets to the reason for this exercise. Once FIG-Forth is loaded it has no use for MicroDOS and its disk structure is incompatible. So no need to have MicroDOS present at all.
But it might be nice to have something that MicroDOS wouldn't hate. So the FIG-Forth disk I/O is altered so that it uses disk blocks starting just after the reserved system tracks. You could create a MicroDOS file that occupied all of that space if you wish.
Yet another question was if the 1802 was afflicted with the same bug as the 6502 version. The answer is no and yes.
ENCLOSE is written as a CODE word and the 6502 version used an 8 bit register to index into the string. This worked great on 8" SS SD disks but failed badly on anything with sectors bigger than 256 bytes. The 1802 doesn't have 8 bit index registers or even an indexed addressing mode. So it doesn't have this bug.
While the 1802 version uses one of its 16 registers to index into the string, it only uses 8 bits of one to compute offsets. Which means that if it encounters say a long string of delimeter characters, there will be trouble. Fixing this one is tricky.
The simplest approach is to edit up the assembler source file to change ENCLOSE. But this makes testing difficult. So unless it works the first time, Forth is broken. The preferred method is to code up a replacement using FIG-Forth so the two can be tested on the same data to see if they give the same results.
Which requires an assembler. Forth assemblers are actually not that hard to write and the 1802 is particularly easy. Although I did punt on doing anything about the short branch problem other than issue an error message when a branch crosses a page boundary.
The hard part is that the structure of ENCLOSE does not fit into the usual FORTH assembler structured conditionals and loops. Two conditions and branches out of the second loop. (One for finding a delimeter and the other for a null.) But by abusing the conditionals I was able to get it done.
I can see a couple of options for making the offsets 16 bits. The first is to extend the offset counter to 16 bits. Simple enough it seems. The second is to ditch that counter completely. Using the current address and just do some math. The starting address is handily one of the return values so is sitting on the stack just waiting for airthmetic operations.
I don't much care for ENCLOSE being a code word. Sure it is faster but is that speed really worthwhile? ENCLOSE is certainly faster than I can type either way. LOADing from disk would be slower but you tend to LOAD once and then use it so a second or two just doesn't matter. But then I remember using the CP/M-68K C compiler with real floppies.