Jump to content
IGNORED

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


Lee Stewart

Recommended Posts

Of course, a quick solution to the graphics mode issue would be to have COLD set the system up into 40 column mode again. This is reasonable, since (at the moment) the graphics mode code (TEXT80 et al) would be expunged from the dictionary upon execution of COLD.

 

To be clear, listing blocks etc. in TEXT80 mode is all fine. It's only when COLD is executed that things go "the way of the pear" ;-)

Link to comment
Share on other sites

Lee,

 

Looking super cool! Now we need the manual ;-)

 

I have more work to do before I even think about the manual! The current fbForth 1.0 manual should be close enough for awhile—except for User Variables. I should probably put together a readme file—maybe soon. I'm having too much fun coding, though! :P

 

...lee

Link to comment
Share on other sites

OK—COLD is fixed (temporarily). For the moment, I'm having COLD look for TEXT . If one has loaded the code for TEXT80 , the code for TEXT is there. If COLD finds TEXT , it is executed and all is well. If one does this from SPLIT or SPLIT2 graphics mode, all hell will likely break loose because the font location was changed and TEXT did not have to be loaded—and CODE does not currently load the default font. That will all be changed when I get graphics stuff to the resident dictionary. Patience—it'll happen.

 

Anyway—here're the corrected files:

 

fbForth200-beta02.zip

fbForth200-beta02-MESS.zip

 

...lee

Link to comment
Share on other sites

I know I requested input for user screen font capabilities before, but here it is again. :P Here's how I currently plan to handle allowing a user to use their own screen font:

  • fbForth 2.0 starts up with a full lowercase font from ROM of my own design from the mid-80s.
  • The user may use their own font file by executing a new word, USEFFL , which I will define as part of the resident dictionary.
    • The user's font will not survive COLD because COLD will load the default startup font.
    • The user may mitigate this by using USEFFL in block #1 of FBLOCKS to point to the desired font file.
  • An fbForth screen-font file must be a binary file with the first 1024 bytes as 8-byte patterns for ASCII 0 – 127—the remainder of the file will be ignored.
  • I will provide a utility for converting CHARA1-style files to fbForth screen-font files; but, I do not plan to use CHARA1-style files. All this means is that a CHARA1-style file needs to have the first 6 bytes removed and the last 6 bytes added as >FFFF, >FFFF, >FFFF—or whatever the user prefers for that part of ASCII 127.

I can change this scenario if there are strenuous objections; but, the above makes loading the font into the PDT very simple by using the LOAD subprogram of the DSR. If I were to use CHARA1-style files, I could still use the LOAD subprogram; but, I would need to

  • save the 6 bytes preceding the Pattern Descriptor Table (PDT)
  • load the file 6 bytes before the PDT
  • ensure the 6 bytes at the end of the PDT are >FFFF, >FFFF, >FFFF
  • restore the 6 bytes before the PDT

What do you think?

 

...lee

 

Link to comment
Share on other sites

I personally would prefer human-readable files (e.g. DV80/DF80) using hex values, one character per line. Simply because it makes it very very easy to make your own font files.

 

A utility for converting CHARA1 files to your own format is all very well, but getting the CHARA1 file in the first place is probably only possible for machine coders (in the sense that, to produce one, you have to use an assembler with your font data in DATA statements then assemble it and convert it to an E/A #5).

 

It would be nice if it could all be done within the Forth environment: E.g. Run a Forth program to produce the CHARA1 file, and then load it with USEFFL. That's the Forth way. Run it. Suck on it. See. Change it. All within the Forth environment.

 

Just my two cents.

 

Having said all of the above, it's trivial to write a Forth routine to read in a text file and define characters using the data file. So maybe I'm making a fuss over nothing!

Link to comment
Share on other sites

I personally would prefer human-readable files (e.g. DV80/DF80) using hex values, one character per line. Simply because it makes it very very easy to make your own font files.

 

A utility for converting CHARA1 files to your own format is all very well, but getting the CHARA1 file in the first place is probably only possible for machine coders (in the sense that, to produce one, you have to use an assembler with your font data in DATA statements then assemble it and convert it to an E/A #5).

 

It would be nice if it could all be done within the Forth environment: E.g. Run a Forth program to produce the CHARA1 file, and then load it with USEFFL. That's the Forth way. Run it. Suck on it. See. Change it. All within the Forth environment.

 

Just my two cents.

 

Having said all of the above, it's trivial to write a Forth routine to read in a text file and define characters using the data file. So maybe I'm making a fuss over nothing!

 

A variation on this is, in fact, my intention (see posts #594ff.). I plan to write a utility that will allow the user to compose a font from scratch or by using an existing font file as a start—in Forth, of course!

 

I suppose I could also write a word to load a text file or Forth blocks (it would take 8 with one char/line). This could be written to allow a subset of any particular ASCII characters to be loaded. This would allow the user to change as many or as few characters as they wish to be different from the default font. I would see the format for such text input (in hex) as

<ASCII|EOC> <word 0> <word 1> <word 2> <word 3>

0041 3844 447C 4444 4400
FFFF 

For the above example, EOC means "end of character list". The first line is only a description and would not be part of the file.

 

...lee

Link to comment
Share on other sites

I am currently looking at the graphics primitives with an eye to putting them in ROM. My current puzzle is the set of constants used for the locations of the various VRAM tables. They are currently defined as Forth constants. They are changed by Forth routines needing to move the tables (constants?!). The method for doing that is

HEX 1B00 ' SATR !   <--SATR is the Sprite Attribute Table

which finds the PFA with ' and stores the value on the stack into the PFA of the constant, where the value is actually stored. Execution of the word SATR then pushes the current value onto the stack. I want to change the "constants" to User Variables for use by various existing routines I will modify to accommodate this change. I can easily write words that give the User Variable's address as well as the contents. I am disinclined to make it convenient for the user to change these constants because fbForth 2.0 will be controlling most of the necessary changes that were expected to be changed by the user in previous versions. The user will know the User Variable offset from the two appendices that describe them and can get to them if s/he must.

 

If I change SATR to use a User Variable, I would want the word SATR to do what it does now as a Forth constant when it is executed, viz., push the value of the User Variable to the stack. The problem this would cause is that the code in the above code window would no longer work because the word SATR 's parameter field would contain a User Variable table offset, not the location of the actual value. Again, it would not be a problem for me because I will change all such existing fbForth code to work properly. The problem is that it would break any existing user code that relies on the ' <constant> ! method to change the constant's value. I am pretty sure there is only one place in the manual that instructs the user to do such a thing—and, it is with only the constant SATR . Therefore, I am inclined to go ahead with my planned changes and just include a user caveat where it was mentioned in previous manuals for fbForth and TI Forth. What do you think?

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Lee, I'm pretty sure this won't create major problems just due to the fact that the SATR routine itself is the only place you would be using the original method out of the box--and that said, it would be easy enough to include a code snippet in your manual that shows how the user should do it now. Then, if there are older programs that use the deprecated method, it becomes a trivial matter to update it to the new one using your code example as a template.

Link to comment
Share on other sites

I'm currently puzzling over how to handle undefining sprites and defining sprites below a newly defined one. Here's the scenario inherited from TI Forth:

  1. Initially, undefine all sprites by setting the y and x values in the attribute table to D000h.
  2. Delete all sprites by doing almost the same thing, i.e., store D0h in all the y values.
  3. If a sprite is defined that has a higher number than an undefined sprite, the undefined sprite has the y,x values set to C001h, i.e., off the bottom of the screen but with x = 1.

I am inclined to only mess with the y values for all of the above because it makes coding much simpler. AFAIK, the x values are irrelevant when the sprite is undefined or off the bottom of the screen, especially, as in 3, it was undefined to begin with. Any reason I should change my mind?

 

...lee

Link to comment
Share on other sites

Remember that the /first/ sprite with a Y coordinate of 0xD0 will disable all the sprites that come after it.. if you just want them offscreen, use 0xD1. ;) But X is certainly irrelevant unless you want to use it to flag something else.

Link to comment
Share on other sites

Yes, exactly. Use >D1. That way, you don't need to run a search to check if lower numbered sprites are disabled. Example: All sprites are set to disabled, and a user wonders why he can't see sprite #31 after he places it on the screen.

Link to comment
Share on other sites

Remember that the /first/ sprite with a Y coordinate of 0xD0 will disable all the sprites that come after it.. if you just want them offscreen, use 0xD1. ;) But X is certainly irrelevant unless you want to use it to flag something else.

 

Thanks for the X idea—it may come in handy some day.

 

Yes, exactly. Use >D1. That way, you don't need to run a search to check if lower numbered sprites are disabled. Example: All sprites are set to disabled, and a user wonders why he can't see sprite #31 after he places it on the screen.

 

That won't happen in fbForth/TI Forth because any word that activates a sprite converts all lower-numbered >D0ed Y coordinates to >C0 so they still appear undefined but are, in actual fact, 1 pixel off the bottom of the screen. I'm not sure why the TI programmers did it this way—I am just preserving that scenario.

 

I do worry about the coincidence flag for sprites that are off the screen and all in the same place (see p. 269 of the E/A Manual). Perhaps I should initialize the "undefined" sprites offset by 16 pixels in 2 rows off the screen, viz., >E000, >E010, ..., >E0F0, >F000, >F010, ..., >F0F0—or maybe 32 pixels for double-sized, magnified sprites. Or, is the E/A Manual wrong about coincidence of sprites off screen?

 

...lee

Link to comment
Share on other sites

I think we've had this sprite-coincidence discussion before. It appears the E/A Manual is wrong about off-screen sprites affecting the coincidence flag. Just putting the sprites off screen should be fine.

 

I suppose the next obvious question is, "Is the VDP processing time affected by not having Y = D0h for the lowest inactive sprite?" My guess is that it is. If you have 5 active sprites by having Y = D0h for sprite #5, I would think the VDP stops processing sprites at that point; but, if sprites #5 – #31 are "inactivated" by forcing them off screen with Y > BFh, I would think the VDP must process all 32 sprites. Does anyone know for sure?

 

...lee

Link to comment
Share on other sites

Do you mean auto motion? It will affect the auto motion as it will give up at the first D0 but I can't imagine it will affect the hardware. I don't know for sure though. Just something in my distant and foggy memory when single stepping the ISR.

Link to comment
Share on other sites

Do you mean auto motion? It will affect the auto motion as it will give up at the first D0 but I can't imagine it will affect the hardware. I don't know for sure though. Just something in my distant and foggy memory when single stepping the ISR.

 

Yeah, it's probably automotion where the delay would be. Because fbForth and TI Forth before it allow a user to use automotion, I should be concerned with that.

 

...lee

Link to comment
Share on other sites

The first sprite with a Y coordinate of 0xD0 will stop the VDP from displaying that and all subsequent sprites. Non-displayed sprites are not considered for collision. Yes, this is in the hardware.

 

Regardless of whether the VDP itself processes all the sprites, there's no difference in performance of the system. At best you might get an additional CPU memory access window (but ISTR you did not. There is no way to tell anyway.)

 

Likewise, offscreen sprites are not considered for collision, and this is wrong in the E/A manual. You can easily see this in Extended BASIC (say, in Classic99) - look at the sprite table when no sprites are visible, and you will see they all overlap offscreen. CALL COINC(ALL) would always trigger a collision if off-screen sprites were considered.

 

0xD0 is meaningless to the automotion routine -- in fact it treats it as a normal Y coordinate. You can easily set up an Extended BASIC automotion to see both that it is used, and that it makes other sprites disappear. There is a byte in scratchpad that specifies how many sprites are processed for automotion. (I don't know it offhand, though). Changing /this/ value makes the console interrupt take more or less time by affecting how many sprites it processes motion for. (Remember that motion has no association with the hardware whatsoever, it's a purely software thing built into the OS).

  • Like 1
Link to comment
Share on other sites

I question the need for taking the absolute value of the differences in lines 3 and 4 of the following fbForth code:

: DXY       ( x1 y1 x2 y2 --- x^2 y^2 )  
    ROT               ( STACK: x1 x2 y2 y1)
    - ABS             ( STACK: x1 x2 |y2-y1|)
    ROT ROT - ABS     ( STACK: |y2-y1| |x2-x1|)
    DUP               ( STACK: |y2-y1| |x2-x1| |x2-x1|)
    * SWAP            ( STACK: |x2-x1|*|x2-x1| |y2-y1|)
    DUP *             ( STACK: |x2-x1|*|x2-x1| |y2-y1|*|y2-y1|)
;

I am pretty sure the same result obtains with or without ABS in this 16-bit code. Anybody know differently?

 

...lee

Link to comment
Share on other sites

Now it's down to MINIT , MCHAR and LINE :-o Of course, MCHAR and LINE are both killers! MINIT initializes VRAM for multicolor mode, MCHAR plots a multicolor character (4-pixel square) and LINE draws a line between 2 sets of coordinates in bitmap mode. I'm getting punchy. I think I'll give it up for tonight. :sleep:

 

...lee

Link to comment
Share on other sites

I rewrote the high-level Forth for MINIT . It works the same but is faster and 14 bytes smaller at 56 bytes. This word was written 2 months after the code for MULTI by the same TI programmer. I am not sure why MINIT was written—all it does is to set up the screen image table (SIT) as recommended in the E/A Manual and code that looks similar is already part of MULTI ! Actually, I do not understand the code for initalizing the SIT in MULTI at all—it looks wrong:

 HEX
 ( init screen image table---LES)
    -1 18 0 DO 
        I 4 / 0FF SWAP 
        DO                  ( vaddr loop [incremented by 8 each pass???]---LES)
            1+ I OVER VSBW 
        8 +LOOP 
    LOOP 
    DROP   

This adds 8 to each byte, starting with 0, which yields this for each of the first 4 screen-rows of the SIT: 00h 08h 10h 18h 20h 28h ... F8h. Four rows later, it is : 01h 09h 11h 19h 21h ... F9h! :-o Each successive 4-row block is different; but, this pattern is quite different from what was probably intended: 00h 01h 02h 03h 04h 05h ... 1Fh for each of the first 4 rows, 20h 21h 22h 23h 24h 25h ... 3Fh for the next 4, etc. I cannot see any other reason for this code except for SIT initialization. I am wondering whether the TI programmer left it that way and just fixed it with MINIT rather than rewriting MULTI .and just included in the manual the fact that MINIT must be executed after MULTI to actually use multicolor mode.

 

Reinforcing this conclusion is the fact that the graphics primitives include MINIT and HCHAR (required by MINIT ) but do not have to be loaded to load and execute MULTI .

 

For the fbForth 2.0 cartridge, I am inclined to call MINIT from within MULTI because all routines needed will be available in ROM—unless someone can point to another reason for the code above (the comments on lines 2 and 5 are mine, BTW). I think I should probably keep MINIT as a word so as not to break the code of all you TI Forth programmers on this forum!?! |:)

 

...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...