Jump to content
IGNORED

fbForth—TI Forth with File-based Block I/O [Post #1 UPDATED: 06/09/2023]


Lee Stewart

Recommended Posts

I'm wondering if you can do tricks with the record size? For example, let's pretend you only had 64 bytes available as a record buffer. Add far as I know, you could still still open and read a D/F 128 file just fine as a DF 64, just double the record number and do two record reads. Would have to check that works though.

 

Depending on how your record read words work (and writes) this might not be a problem. If your words require a buffer in cpu ram to hand of the records to then its not a problem. Just do two reads placing the data in the appropriate place in the users buffer with each read.

 

Like I say. .. Would have to try it!

 

The file I/O words that are described in Chapter 8 of the TI Forth Instruction Manual do, indeed, require a RAM buffer in addition to a VRAM buffer. They also need to be the same size. I won't be using those for fbForth's block I/O, however. I will be reading 128 bytes X 8 to fill one of the 5 block buffers in low RAM each time a block is read and vice versa for writes.

 

...lee

Link to comment
Share on other sites

...Also, fbForth will only have a blocks file open when a read/write is in progress—I believe that's how @Willsy does it in TurboForth. It will be closed at all other times, whereas a user may keep files open between reads/writes. :-o This does present a potential problem I hadn't thought of, however. It is possible that the user could have the maximum number of files open at a point when Forth blocks need to be accessed. This would cause a file error that probably would not occur in TI Forth! This will obviously be the most serious in bitmap mode, where FILES=1 and FILES=2 are the only options. Perhaps a caveat in the user manual will suffice—I don't know. :? I suppose I should add another error message for this purpose.

 

...lee

Link to comment
Share on other sites

As long as it is documented, then it's fine. Then it's a case of user beware! The real question is what should your system do when this happens? Probably the only thing you can do is an ABORT back to the command line, with an appropriate error message. At that point, the programmer will know what to do (i.e. close one of his files before making a block access, then open his file again).

 

Yep, TF always keeps the file closed. It opens the blocks file, does it's thang, then closes it again. This is both for safety (it's easy to crash any Forth system!) and pragmatic reasons; it was just simple (and natural) for BLOCK to open the file, so it's thing, and close it again. This has a performance penalty on floppy systems, as the head continually visits the directory (as far as I can ascertain) with each open/close cycle. However, on emulators, and RAM disks/CF7 etc, you don't notice it at all. For FLUSH, I have it open the disk file, and flush all appropriate blocks to disk, then close the file. There's no open/flush buffer/close open/flush/close stuff going on - that would just be silly ;)

Link to comment
Share on other sites

This map has been modified (see post #259).

 

Here is the current VRAM map for fbForth's bitmap mode:

*

0000h ┬──Bitmap Color Table
      │    1800h (6144) bytes
1800h ┼──Bitmap Screen Image Table
      │     300h (768) bytes
1B00h ┼──Value Stack (@VSPTR)  <start discretionary VRAM>─┐
      │      40h (64) bytes                               │
1B40h ┼──Forth Disk Buffer (@DISK_BUF)                    │
      │      80h (128) bytes                              │
1BC0h ┼──User PABS etc.                                   │
      │      86h (134) bytes                              │
1C46h ┼──Forth System Messages                           500h
      │     176h (374) bytes                              │
1DBCh ┼──True Lowercase Characters                      (1280)
      │      F8h (248) bytes                              │
1EB4h ┼──PAB for Current Blocks File                    bytes
      │      46h (70) bytes                               │
1EFAh ┼──PAB for Second Blocks File                       │
      │      46h (70) bytes                               │
1F40h ┼──Default system FBLOCKS pathname                  │
      │      3Ch (60) bytes                               │
1F80h ┼──Sprite Attribute List                            │
      │      80h (128) bytes                              │
1FFFh │                          <end discretionary VRAM>─┘
2000h ┼──Bitmap Pattern Descriptor Table
      │    1800h (6144) bytes
3800h ┼──Sprite Attribute Descriptors
      │     1DEh (478) bytes
      │        (space for sprites 0–58)
39DEh ┼──Disk Buffer Region for 2 Disk Files
      │     622h (1570) bytes
3FFFh │
      └───

*

Presuming that I leave True Lowercase and Messages in the mix, the only wiggle room I have is to put the Sprite Attribute List back where TI Forth has it, viz., 3800h, which cuts the available Sprite Attribute Descriptors down to 16–58 (TI Forth's limitation) from 0–58. That would bring the User PABs (etc.) area to 262 bytes. The Forth disk buffer area can be used by the user as long as any user files are closed when the user is using Forth blocks. Because those two areas are contiguous, user PAB(s) can be backed up against the Messages area and the remainder used for disk buffer(s) with the foregoing caveats. My guess is that the user probably won't be making much use of files other than Forth blocks when in bitmap mode and that the above restrictions are not that onerous.

 

Before I move on to coding all of this, I should probably analyze what is going on in SPLIT and SPLIT2 modes with the VRAM map just to make sure I'm not stepping in something. :P

 

...lee

  • Like 1
Link to comment
Share on other sites

Though there appears to be much to grumble about with this recent AA "upgrade", at least the Code tool, when choosing "none" for the code type, does not presume to know what I intend by removing spaces and generally screwing up its readability—witness, my little VRAM map a couple of posts back! :D

 

...lee

  • Like 1
Link to comment
Share on other sites

A few things regarding fbForth system error/warning messages—

  1. I have reduced them to 301 bytes (down from 374) because some of them are not used in TI Forth and certainly won't be used in fbForth. This raises the amount of space in the "User PABs etc." area to 206 bytes (see VRAM map 3 posts back).
  2. I could gain another 19 bytes by simplifying the message, "compilation only; use in definition", to "compilation only". I don't think the extra verbiage adds that much clarity to the message. @Willsy? Other Forthers?
  3. Now, I need a convenient way to index the messages—at the moment, they are referenced by number and those numbers are not contiguous. They range from 1–25. Currently, fbForth has just 16 messages. I could set up an index table of 50 bytes in low RAM and copy the VRAM addresses of each of the 16 messages to their respective locations and 0 to the unused locations. I could do this easily with address calculations that include the VRAM address of the true lowercase patterns. I will be copying the messages from RAM (located in a part of the fbForth program that will be discarded once fbForth gets control) to VRAM just in front of the TLC patterns. I could label each message's temporary RAM location to aid in the address calculation. Then, when fbForth needs a message displayed, it gets the offset into the low RAM table to get the VRAM address of the message, copies the message to PAD and uses COUNT and TYPE to display it. Or...does someone have a better idea?

...lee

Link to comment
Share on other sites

Well—I guess I'm talking to myself again; but, as I've said before, it does help me to organize my thoughts and document the process.

 

I am in the process of again rearranging the discretionary part of the VRAM map for bitmap mode (see post #254). At the very least, I want to put the PABS area for user PAB(s) and buffer(s) ahead of the fbForth disk buffer instead of behind it. My problem is where to put the Value Stack, which, in bitmap mode, is only 64 bytes deep—enough for 8 floating point numbers. I would guess that the reason the TI Forth developers put it immediately ahead of the Forth disk buffer is that it could bleed into the Forth disk buffer without causing much of a problem because that buffer is strictly temporary. I was hoping to do the same thing with PABS for the same reason; but, then, if I put the Value Stack ahead of PABS, I would need to know what danger there might be that PABS would get clobbered. FYI, the Value Stack and FAC are used by 5 XML floating point operations (see pp. 260–1 of the Editor/Assembler Manual). In modes other than bitmap, the Value Stack is twice as deep and is, in fact, just ahead of PABS. Does anyone know how deep the Value Stack can get pushed and, for that matter, when the Value Stack XML routines ever get used if the user doesn't call them? :? fbForth never calls them explicitly—it calls the FAC/ARG equivalents instead (see pp. 259–60 of the E/A Manual).

 

I suppose the GPL transcendental functions could be using the Value Stack; but, I would need to parse GROM0 in TI99/4A Intern to get a handle on that! Anybody know? :?

 

...lee

Link to comment
Share on other sites

VRAM map for fbForth's bitmap mode (modified from earlier post):

*

0000h ┬──Bitmap Color Table
      │    1800h (6144) bytes
1800h ┼──Bitmap Screen Image Table
      │     300h (768) bytes
1B00h ┼──Sprite Attribute List <start discretionary VRAM>─┐
      │      80h (128) bytes                              │
1B80h ┼──User PABS etc.                                   │
      │      E2h (226) bytes                              │
1C62h ┼──Value Stack (@VSPTR)                             │
      │      40h (64) bytes                               │
1CA2h ┼──Forth Disk Buffer (@DISK_BUF)                    │
      │      80h (128) bytes                              │
1D22h ┼──Forth System Messages                         500h <─┐
      │     11Ch (284) bytes                         (1280)   │
1E3Eh ┼──True Lowercase Characters                    bytes   │
      │      F8h (248) bytes                              │   │
1F36h ┼──PAB for Current Blocks File                      │ [move]
      │      46h (70) bytes                               │   2DEh
1F7Ch ┼──PAB for Second Blocks File                       │   (734)
      │      46h (70) bytes                               │   bytes
1FC2h ┼──Default system FBLOCKS pathname                  │   │
      │      3Dh (61) bytes  (includes char count)        │   │
1FFFh │        (+1 empty byte)   <end discretionary VRAM>─┘ <─┘
2000h ┼──Bitmap Pattern Descriptor Table
      │    1800h (6144) bytes
3800h ┼──Sprite Attribute Descriptors
      │     1DEh (478) bytes
      │        (space for sprites 0–58)
39DEh ┼──Disk Buffer Region for 2 Disk Files
      │     622h (1570) bytes
3FFFh │
      └───

*

Note that the 734-byte persistent area that gets moved when the mode is changed to/from bitmap mode always starts 128 bytes after DISK_BUF , the beginning of the 128-byte fbForth disk buffer, regardless of the mode.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

I need a little advice here—

 

I may be trying to be too clever just to save a little space! My Message Table Index (MTIDX) can be 26 bytes instead of 52 if I subtract the message number from the offset into the message table and add it back before indexing into the VRAM location of the message table. The reason the index would otherwise need to be word-oriented instead of byte-oriented is that the last message table entry is offset by a number greater than 255. By subtracting the message number from the offset, all are within byte range and none are 0 unless there is no message in that slot. By adding an extra word (16 bits) to the head of the message table (could be used for highest message number), the pseudo-index of the first message will be 1 instead of -1, which would complicate things. I could then retrieve the message address as follows:

*

       LI   R0,MTIDX      get index table start
       A    *S,R0         add message number from stack
       CLR  R1
       MOVB *R0,R1        move table offset byte from index table to R1
       JEQ  DONE          return 0 if no message
       SWPB R1            put in right byte
       A    *S,R1         restore table offset
       A    @VFSM,R1      get address of VRAM location of message character count byte
*                            (VFSM is fbForth system message table start in VRAM)
DONE   MOV  R1,*S         return VRAM address or 0 to stack
*                            (we might do this another way, later) 

*

What do you think? @Willsy? @matthew180? @mizapf? @Tursi? @Vorticon? @senior_falcon? @jacquesg? @sometimes99er? @marc.hull? @RXB? @Opry99er? ? Anyone else?

 

...lee

Link to comment
Share on other sites

I used to fight for every byte, but these days, even on the TI, I don't think I'd blink at saving 26 bytes of RAM if the code/performance tradeoff was too big.

 

I don't know the original code, I assume it's a single instruction, but the block you posted takes 22 bytes. If your original code was 4 bytes, then the code increase is 18 bytes, meaning instead of saving 26 bytes, you're only saving 8. (* If code and data are both in RAM, of course. Code in ROM and data in RAM renders this argument moot).

 

If this is core to the interpreter loop (I don't follow it's intent), I'd be inclined to prefer the faster code. :)

Link to comment
Share on other sites

*

 

Note that the 734-byte persistent area that gets moved when the mode is changed to/from bitmap mode always starts 128 bytes after DISK_BUF , the beginning of the 128-byte fbForth disk buffer, regardless of the mode.

 

...lee

 

-

Are you deriving the disk buffer VDP address from 0x8370? The value does change depending on hardware. ;)

Link to comment
Share on other sites

I used to fight for every byte, but these days, even on the TI, I don't think I'd blink at saving 26 bytes of RAM if the code/performance tradeoff was too big.

 

I don't know the original code, I assume it's a single instruction, but the block you posted takes 22 bytes. If your original code was 4 bytes, then the code increase is 18 bytes, meaning instead of saving 26 bytes, you're only saving 8. (* If code and data are both in RAM, of course. Code in ROM and data in RAM renders this argument moot).

 

If this is core to the interpreter loop (I don't follow it's intent), I'd be inclined to prefer the faster code. :)

 

There is no original code for this and it is not in the interpreter loop. I have simply hoisted the messages from constant disk access to VRAM. I am only puzzling over the best way to retrieve them.

 

...lee

Link to comment
Share on other sites

*

 

Note that the 734-byte persistent area that gets moved when the mode is changed to/from bitmap mode always starts 128 bytes after DISK_BUF , the beginning of the 128-byte fbForth disk buffer, regardless of the mode.

 

...lee

 

-

Are you deriving the disk buffer VDP address from 0x8370? The value does change depending on hardware. ;)

 

No. This buffer is different and completely under my control. See next post.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

*

 

Note that the 734-byte persistent area that gets moved when the mode is changed to/from bitmap mode always starts 128 bytes after DISK_BUF , the beginning of the 128-byte fbForth disk buffer, regardless of the mode.

 

...lee

 

-

Are you deriving the disk buffer VDP address from 0x8370? The value does change depending on hardware. ;)

 

Oops! I think I misunderstood your question? :dunce: In fact, I pretty much am doing that. TI Forth actually has the VRAM max wrong by 4 bytes when 2 files are allowed. The Sprite Attribute Descriptor Table is actually backed up against it and is the reason the maximum code for sprite patterns in bitmap mode is 58. The actual TI Forth code for the switch to bitmap mode sets FILES = 1, which then allows sprite pattern codes up to 123; but, TI never says that anywhere in the manual and I did not catch it in time for my second edition of the manual. I may well need to actually make FILES = 2, now that fbForth will be using level 3 disk file I/O routines for block I/O, so that the user can have one file open. This causes another problem to surface that I'm not sure how to handle except, possibly, with a better error message than "file I/O error". The problem would occur if the user has the maximum number of files open and the need arises to open the current blocks file. It would obviously fail, giving the aforementioned error message. I suppose I could just rely on a strident caveat in the bitmap-mode section of the forth |:) coming fbForth Instruction Manual. Also, is there an open file counter maintained anywhere? If not, perhaps I should maintain one in fbForth.

 

...lee

Link to comment
Share on other sites

I don't remember seeing an open file counter, I think it just checks to see if any of the buffers are free when a new one is needed. There's a block of data at the beginning of the VDP buffer space that can't be corrupted, so you can't overflow into the lowest buffer even if it's unused, if that was your intent. :)

 

Remember that setting "FILES=x" is not enough to /know/ the top of free VDP space -- devices like the CF7 allocate extra VDP memory for their own use (6 bytes in this case) which will change the free address.

Link to comment
Share on other sites

I don't remember seeing an open file counter, I think it just checks to see if any of the buffers are free when a new one is needed. There's a block of data at the beginning of the VDP buffer space that can't be corrupted, so you can't overflow into the lowest buffer even if it's unused, if that was your intent. :)

 

Remember that setting "FILES=x" is not enough to /know/ the top of free VDP space -- devices like the CF7 allocate extra VDP memory for their own use (6 bytes in this case) which will change the free address.

 

I was aware of the CF7's 6 bytes; but, I'm asea when it comes to other devices. Those 6 bytes cut down the sprite patterns by 1. Obviously, devices that take a lot of extra space could cause me serious trouble. At the moment, there is enough space for 59 sprite patterns with FILES=2 for diskette controllers (58 with CF7 in the mix). TI Forth only allowed 43. That gives me 128 bytes before fbForth is at the TI Forth sprite pattern count for bitmap mode. I suppose I should have the system check 8370h just before it goes into bitmap mode to discover the sprite situation and inform the user of the number of sprite patterns available if it is fewer than a certain number. If DSR space encroaches on 37FFh (upper end of Bitmap Pattern Descriptor Table), I will have to inform the user that bitmap mode is not available.

 

Do you know how much extra space other DSRs grab, particularly, one like a hard disk controller? I'm trying to accommodate longer pathnames for blocks files by giving them the full 60 bytes that the E/A cartridge allows.

 

...lee

Link to comment
Share on other sites

Remember that setting "FILES=x" is not enough to /know/ the top of free VDP space -- devices like the CF7 allocate extra VDP memory for their own use (6 bytes in this case) which will change the free address.

 

CF7 devices use 8 bytes ;) The DSR adjusts 0x8370 to compensate though some programmers use(d) hard-coded values.

Link to comment
Share on other sites

6, 8, whatever it is (I thought 6!)... at any rate, the point is that instead of trying to predict everything up front, just read >8370 and it tells you the highest VDP address you are allowed to use. :)

 

Do you know what I can expect for something like a hard disk controller? (see my last post)

 

...lee

Link to comment
Share on other sites

6, 8, whatever it is (I thought 6!)... at any rate, the point is that instead of trying to predict everything up front, just read >8370 and it tells you the highest VDP address you are allowed to use. :)

Sorry, been debugging a nasty DSR bug this evening and just "blurted" that out while taking a quick break. Your point about reading 0x8370 is spot on. Back to the ol' 13" CRT screen I go... :-o

Link to comment
Share on other sites

I could define a word, say SPCHARMAX that reports the highest available sprite character number for bitmap mode. I would need to check the maximum number of files, which is 5 bytes above the VRAM max reported in 8370h. The trouble with that is that I won't be able to do it in Classic99 because Classic99 doesn't update that area like the real iron does. :_(

 

I suppose I could create a couple of system user variables, say FILEMAX and FBUFCHUNK , to keep track of the 'x' of FILES = x and the VRAM chunk required for each file, respectively. Unless someone can tell me it's always 518 bytyes, :? I will need to take the difference of what 8370h reports for FILES = 2 and FILES = 3 at startup for FBUFCHUNK . I would need to modify the definition of FILES to update FILEMAX .

 

Anybody have a better idea?

 

...lee

Link to comment
Share on other sites

I could define a word, say SPCHARMAX that reports the highest available sprite character number for bitmap mode. I would need to check the maximum number of files, which is 5 bytes above the VRAM max reported in 8370h. The trouble with that is that I won't be able to do it in Classic99 because Classic99 doesn't update that area like the real iron does. :_(

That's the only thing it does will CALL FILES (or the asm equivalent) is update that pointer. It doesn't fill that area in with any data, is all. You should be able to test that much.

 

(re-reading.. you are trying to pull data out of that area. Again.. you shouldn't assume the operation of the disk controllers, IMO. Let them be black boxes and you will have fewer compatibility issues.)

 

I suppose I could create a couple of system user variables, say FILEMAX and FBUFCHUNK , to keep track of the 'x' of FILES = x and the VRAM chunk required for each file, respectively. Unless someone can tell me it's always 518 bytyes, :? I will need to take the difference of what 8370h reports for FILES = 2 and FILES = 3 at startup for FBUFCHUNK . I would need to modify the definition of FILES to update FILEMAX .

I'm still not clear why you can't just check >8370 any time you need to know the top of VRAM. You definitely should not be using 5 bytes ABOVE that value -- you may corrupt important data. I understand you're trying to calculate the highest available sprite pattern, but you should be able to just look at >8370 and be done with it, rather than trying to estimate the size of file buffers and interpret the actions of various disk controllers.

 

If you can help me understand why the pointer is not enough, I can try to help with some ideas. :)

Edited by Tursi
Link to comment
Share on other sites

...

I'm still not clear why you can't just check >8370 any time you need to know the top of VRAM. You definitely should not be using 5 bytes ABOVE that value -- you may corrupt important data. I understand you're trying to calculate the highest available sprite pattern, but you should be able to just look at >8370 and be done with it, rather than trying to estimate the size of file buffers and interpret the actions of various disk controllers.

 

If you can help me understand why the pointer is not enough, I can try to help with some ideas. :)

 

The problem is that once bitmap mode is invoked, fbForth (and TI Forth) cannot easily give the user any information because there is no text area on the screen. I need to be able to figure it out before bitmap mode is invoked to let the user know if they have fewer sprite pattern descriptors available than what the manual will say. I don't know what the situation was with TI forth with longer pathnames than device names—it probably wasn't pretty. I just think fbForth should warn the user if the situation is unusual. I don't think the developers of TI Forth thought about anything but diskette drives, so maybe I shouldn't either; but, if different-sized buffers are allocated with other than diskette drives, I'd like to know and relay the information to the user.

 

Edit: I should add that there is an unconditional change of FILES=2 (or maybe I'll change it to FILES=1 as with TI Forth, I don't know, yet), when changing to bitmap mode from whatever it was (default is 3) before the change.

 

...lee

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...