Jump to content

Photo

Camel99 Forth Information goes here

Camel99 Forth Concatentive Programming ANS Forth

190 replies to this topic

#76 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Fri May 11, 2018 5:52 PM

I have developed a healthy respect for the authors of the Sprite control in X-BASIC.

I found this old XB Demo program and wondered how I could do it in "GOLLY GEE WHIZ" Forth.

Without Automotion I had to create a timer variable for each motion element and down count to zero, like the ROM code does.

 

Was able to gain some efficiency by creating words that only play with X or Y in a sprite independently.

 

Anyway for those studying Forth this might provide some ideas.

 

Spoiler

 

 

Attached Files



#77 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,287 posts
  • HarmlessLion
  • Location:BUR

Posted Tue May 15, 2018 1:20 AM

Hah, that looks familiar. ;) I wrote that for the Summerland TI Users Group back when I was still in high school, based on a picture in 99er Magazine (was part of an explanation of sprites). ;)

(edit: the original XB version, that is ;) )

Edited by Tursi, Tue May 15, 2018 1:20 AM.


#78 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Wed May 16, 2018 8:37 AM

Hah, that looks familiar. ;) I wrote that for the Summerland TI Users Group back when I was still in high school, based on a picture in 99er Magazine (was part of an explanation of sprites). ;)

(edit: the original XB version, that is ;) )

 

You know you are history when... :-)

 

That's really cool.  Thanks for letting everybody know.

 

B



#79 D-Type OFFLINE  

D-Type

    Space Invader

  • 17 posts
  • Location:Zürich

Posted Thu May 17, 2018 3:53 PM

So now there's 3 Forth systems for the TI?

I assume this one is based on Brad's Camel Forth?

But, by the look of it, you're not cross compiling from a PC?

I'm also using Brad's Camel Forth, but the 6809 variant and using his Chromium cross compiler.

Target is the Vectrex, probably a lot less work than you need to put it as it has the correct processor!

#80 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Thu May 17, 2018 5:05 PM

So now there's 3 Forth systems for the TI?

I assume this one is based on Brad's Camel Forth?

But, by the look of it, you're not cross compiling from a PC?

I'm also using Brad's Camel Forth, but the 6809 variant and using his Chromium cross compiler.

Target is the Vectrex, probably a lot less work than you need to put it as it has the correct processor!

 

 

Yes I am the last of the noble group.  I am cross-compiling actually.  On a "real" PC,  the DOSBOX. :-)

 

The cross-compiler is here.  https://github.com/b...master/Compiler

It actually began with the TI-Forth assembler that I modified to assemble into a different memory segment.

 

It runs on an old DOS Forth from the '90s called HsForth which I upgraded to something a little closer to ANS Forth.

 

I stripped the comments from Brad's MSP430 Camel Forth Assembly Language source , which are Forth and wrote the compiler to compile the comments. :-)  It still had to write all the primitives in 9900 assembler however.

 

Edit: The cross-compiler builds an 8K kernel that can extend itself with source code.

The latest version now can compile TI DV80 source files and I have the beginnings of ANS file word set support.

 

I had to do it the hard way. It's been on my bucket list for 35 years to make a cross-compiler so time was running out.

 

 

Brian


Edited by TheBF, Thu May 17, 2018 5:16 PM.


#81 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Thu May 17, 2018 9:14 PM

Improved Background Sound List Player

 

Spent some time working on what I think can be my goto sound list player. 

I will test it a little harder and then put it up on GitHub.

But I notice that even though it does not use interrupts it plays very solid when I exercise the screen heavily.

 

The features are:

  1. It can Queue up to 16 sound lists
  2. Sound lists are stored in VDP RAM
  3. Code includes VDP byte directive so lists are as easy to code as Assembler
  4. Player task goes to sleep when sound Queue is empty
  5. Uses the TMS9901 timer for sound duration
  6. Task memory is allocated in Low RAM
  7. Size: Multi-tasker, VDP memory manager, VDP byte compiler, BG player adds 1218 bytes to the Forth dictionary
  8. >SNDQ command enqueues a sound list
  9. PLAYQ command plays whatever is the sound queue
  10. KILLQ command emptys the sound queue. (playing sounds will continue until finished)

Sound lists look like this:

VCREATE NOKIA
       VBYTE 01,9F,20
       VBYTE 03,90,85,05,09
       VBYTE 02,8F,05,09
       VBYTE 02,87,09,12
       VBYTE 02,87,08,12
       VBYTE 02,85,06,09
       VBYTE 02,81,07,09
       VBYTE 02,8E,0B,12
       VBYTE 02,8A,0A,12
       VBYTE 02,81,07,09
       VBYTE 02,8F,07,09
       VBYTE 02,8A,0C,12
       VBYTE 02,8A,0A,12
       VBYTE 02,8F,07,24
       VBYTE 01,9F,00
/VEND
Spoiler

Edited by TheBF, Thu May 17, 2018 9:25 PM.


#82 Lee Stewart ONLINE  

Lee Stewart

    River Patroller

  • 3,760 posts
  • Location:Silver Run, Maryland

Posted Fri May 18, 2018 6:08 AM

Brian...

 

I would like to be more involved, but my focus for a few weeks is getting my left knee back to normal function after successful surgery.  I am not looking for sympathy—just explaining why I have not been more responsive.

 

You would not, perchance, be coming to the Chicago Faire in November, would you?

 

...lee



#83 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Fri May 18, 2018 6:31 AM

Brian...

 

I would like to be more involved, but my focus for a few weeks is getting my left knee back to normal function after successful surgery.  I am not looking for sympathy—just explaining why I have not been more responsive.

 

You would not, perchance, be coming to the Chicago Faire in November, would you?

 

...lee

 

 

Hi Lee,

 

No worries.   First things first is always a good strategy.

 

I have been feeling off myself with a flu like thing.

 

 I have not given Chicago any thought.  It would be a significant expense but would be fun I'm sure.  I will give it some thought.

 

Brian



#84 D-Type OFFLINE  

D-Type

    Space Invader

  • 17 posts
  • Location:Zürich

Posted Mon May 21, 2018 7:30 AM

 

 

Yes I am the last of the noble group.  I am cross-compiling actually.  On a "real" PC,  the DOSBOX. :-)

 

The cross-compiler is here.  https://github.com/b...master/Compiler

It actually began with the TI-Forth assembler that I modified to assemble into a different memory segment.

 

<<CHOP>>

 

Brian

 

Ah yes...actually I read your release notes etc. perhaps 4 or 5 weeks back, then I went on holiday for a week and forgot everything about it :-) My memory now of what I read is that you compiled (assembled?) the primitives and put that onto the '99 and then loaded the rest of Forth and any extensions using the '99 to compile. When you've got access to disk/flash, I guess that gives you a nice usable system to do that.

 

My CamelForth is running on 6809 and Brad R's "Chromium" cross-compiler is quite complete, so I'm compiling everything on the PC. As the target is the Vectrex with it's vector monitor and joystick, there is no keyboard or character-based display, and <1k of usable RAM, so compiling on the Vectrex is a non-starter without hardware mods. I do have a serial port/terminal added to mine for interactive testing, but a ~700 byte dictionary has some limitations!

 

My aim is to allow creation new cartridge programs/games by other developers, so hardware changes can only be minimal, thus PC is the IDE. There are some great emulators for the Vectrex with build-in debuggers and one has a full IDE for assembly language development, but it still works quite nicely with the output from the Chromium compiler. With some help from the Forth community, I have Camel Forth 6809 Chromium compiler now running on Gforth instead of F83 and with plain text files instead of block files, I saw this as mandatory to get any new users. One day I'll learn how to use Github...

 

I'm new to the TI processors,a quick look shows the 430 to be similar to the '99 processor, but with more capability, so it makes perfect sense to port 430 Camel Forth to the '99.

 

It looks like you've put a lot of effort into your Forth, just like the other two Forths for the TI, they all look excellent. I've really enjoyed reading about them and the '99 in general, especially after learning so much about the machine on the Floppy Days series of '99 podcasts. I owe it to myself to download Classic99 and give'em a go!


Edited by D-Type, Mon May 21, 2018 7:34 AM.


#85 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,383 posts
  • Location:Germany

Posted Mon May 21, 2018 7:51 AM

I'm new to the TI processors,a quick look shows the 430 to be similar to the '99 processor, but with more capability

 

This is what I recently learned about as well, and indeed, there is quite some similarity. People who know TMS9900 should have a look here: https://en.wikipedia...P430#MSP430_CPU



#86 D-Type OFFLINE  

D-Type

    Space Invader

  • 17 posts
  • Location:Zürich

Posted Mon May 21, 2018 9:06 AM

 

Ah yes...actually I read your release notes etc. perhaps 4 or 5 weeks back, then I went on holiday for a week and forgot everything about it :-) My memory now of what I read is that you compiled (assembled?) the primitives and put that onto the '99 and then loaded the rest of Forth and any extensions using the '99 to compile. When you've got access to disk/flash, I guess that gives you a nice usable system to do that.

 

<<CHOP>>

 

Actually something I forgot to mention, I once owned a TI-99/4A. I can't remember where I got it from, but my eBay auction text from Jan 2002 when I listed it said "This is an auction for a Texas Instruments TI99/4A computer main unit only. I have no power supply or other leads so I do not know if it works."

 

No wonder I can't really remember much about it, except it seemed really nicely made. I'm a bit sad now that I didn't stick it in a box in the garage for later!


Edited by D-Type, Mon May 21, 2018 9:06 AM.


#87 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,383 posts
  • Location:Germany

Posted Mon May 21, 2018 9:46 AM

I recently pondered over throwing away my old analog SLR camera. Better not. It would not have been the first time that I regret throwing away something later.



#88 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Tue May 22, 2018 6:36 PM

 

Ah yes...actually I read your release notes etc. perhaps 4 or 5 weeks back, then I went on holiday for a week and forgot everything about it :-) My memory now of what I read is that you compiled (assembled?) the primitives and put that onto the '99 and then loaded the rest of Forth and any extensions using the '99 to compile. When you've got access to disk/flash, I guess that gives you a nice usable system to do that.

 

My CamelForth is running on 6809 and Brad R's "Chromium" cross-compiler is quite complete, so I'm compiling everything on the PC. As the target is the Vectrex with it's vector monitor and joystick, there is no keyboard or character-based display, and <1k of usable RAM, so compiling on the Vectrex is a non-starter without hardware mods. I do have a serial port/terminal added to mine for interactive testing, but a ~700 byte dictionary has some limitations!

 

My aim is to allow creation new cartridge programs/games by other developers, so hardware changes can only be minimal, thus PC is the IDE. There are some great emulators for the Vectrex with build-in debuggers and one has a full IDE for assembly language development, but it still works quite nicely with the output from the Chromium compiler. With some help from the Forth community, I have Camel Forth 6809 Chromium compiler now running on Gforth instead of F83 and with plain text files instead of block files, I saw this as mandatory to get any new users. One day I'll learn how to use Github...

 

I'm new to the TI processors,a quick look shows the 430 to be similar to the '99 processor, but with more capability, so it makes perfect sense to port 430 Camel Forth to the '99.

 

It looks like you've put a lot of effort into your Forth, just like the other two Forths for the TI, they all look excellent. I've really enjoyed reading about them and the '99 in general, especially after learning so much about the machine on the Floppy Days series of '99 podcasts. I owe it to myself to download Classic99 and give'em a go!

 

 

For 100% clarity it cross-assembles about 100 primitives into the binary image and then using cross-compiler magic and those primitives you cross-compile the ANS/ISO Forth CORE word set and quite a bit of the extended word set.  And the system includes simple file access and the word "INCLUDED".

 

So with  :   ;  and INCLUDED I can load and compile anything else that is needed.

 

I can also use the XFC99 Cross-compiler to create stand alone 99 programs but currently they are limited to 8K in size.

 

I don't know much about github either.  I can get files up there but have not yet grokked version control.  Not that interested to be honest, but I guess I should try harder.

 

Well done on moving Chromium to gForth.

I have dreams of porting my cross-compiler to gForth as well.  So much code, so little time...

 

There are things about MSP430 that are nice like a real stack pointer  and instructions that execute in 2 or 3 clocks instead 14 to 28.  :mad:

The 9900 has the faster context switch, at least in terms of instructions. But yeah it's  a pretty easy conversion for many primitives.

 

B



#89 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Thu May 24, 2018 9:00 PM

Performance Enhancements in ANS Forth

 

I am going to release a pretty near final version of the instruction manual and it includes this chapter that might be interesting to the Forth experimenters here.

 

 

Performance Enhancements

As we have seen Forth operates like everything is a sub-routine. In many languages this would cause a big overhead but Forth was built to minimize sub-routine overhead.

One way it does this is by using separate stacks for data and return addresses.  Even so there are times when you need every bit of speed you can get.

This can mean that calling a routine in a time critical loop makes things too slow.

Text Macros

The solution to removing some calling overhead is to use a feature that became part of Forth in the ANS Forth 94 Standard. 

The name of the feature is the “Text Macro” and it combines a literal text string and the word EVALUATE. 

Consider the following code:

INCLUDE DSK1.ELAPSE.F   \ elapsed timer utility

\ Calculate the address of an array at index ‘n’
: []  ( ndx addr – addr[n])  SWAP CELLS + ;

\ store n in array at ndx
: []! ( n ndx addr -- ) [] ! ;

\ fetch n from array at ndx
: []@ ( ndx addr – n)   [] @ ;

DECIMAL 
2000 CONSTANT SIZE

CREATE Q  SIZE CELLS ALLOT    \ make some space called Q
: FILL-Q    SIZE 0 DO  I  I Q []!  LOOP ;
: SEE-Q     SIZE 0 DO     I Q []@ . LOOP ;
: EMPTY-Q   SIZE 0 DO     I Q [] OFF  LOOP ; 

This code will work as expected and you can fill the array, see-the-array and empty the array.

If we run this we get the following results:

 

(Example 1 jpeg)

 

 

Now let’s replace the array index calculator with a TEXT Macro like this:

: []    S” SWAP CELLS +” EVALUATE ;  IMMEDIATE

 

What’s the difference?  When word [] runs now it will take the text string and interpret it.  That’s normal, but now consider what happens when we do this:

\ store n in array at ndx

: []! ( n ndx addr -- ) [] ! ;

 

Notice that now [] is an IMMEDIATE word.  This means that the text string will be interpreted while we are compiling the definition of []!   The effect of this we be that the compiler will compile SWAP CELLS + as separate words into the routine []!.   This therefore means that there will no longer be a sub-routine call to [], but rather a call to each of the separate words. In other words we have compiled the definition of [] “inline”. 

Let’s see what it does to the speed of our loops.

 

​(Text macros jpeg)

 

We get a 15% speed improvement in the first case and a 21% improvement in the second case.  The downside of using text macros is that every time we use [] we consume 3 CELLS ( 6 bytes) of space rather than only 1 CELL with a colon definition.  So use TEXT macros wisely and you can get some improvements in your code speed with very little effort.

INLINE CODE WORDS

CAMEL99 Forth is implemented as something called an "indirect threaded code". This is a very clever way to make a language that fits a lot of stuff in a small space. The secret to this code density is that every routine is identified by just one address.  The secret to making it run quickly is creating a little routine to read those addresses and do the code associated with them as fast as possible. On the TMS9900 that little routine is 3 instructions of assembly language so it's pretty fast but there is a price penalty with threaded code that can range from 2.5 times to as much as ten times in the worst cases.

It turns out that ITC Forth spends about 50% of the time running those three instructions that read the address which sometimes is called the [1]inner interpreter and is given the name NEXT.

At the bottom of every Forth system are a pile of little routines written in assembler (CODE words) that do all the real work. They are simple things that read the contents of a memory address or add two numbers together. The code is all there and it is normally just called by the inner interpreter. Each routine ends with a call back to the inner interpreter.

Wouldn't it be handy if we could use all that code the way a conventional compiler does and copy the routines into memory all in row and eliminate the inner interpreter between each CODE word?

CAMEL99 has INLINE[ ] to do just that.  It reads a string of Forth words that are assembly language words and strings the code together as one long routine. This is not as space efficient, but it can as much as 2.4 times faster!  Below is an example of how we could use CODE words to improve the speed of our previous example but not write one instruction of Assembly language.  Notice we have only changed the array indexing words to CODE words. 

The Magic is done with INLINE[ ] which compiles each code word but strips off the call to NEXT and lets each CODE word run one after the other.  This is ONLY possible with system CODE words.  If you attempt to INLINE[] Forth words the compiler will ABORT with an error message.

INCLUDE DSK1.ELAPSE.F   \ elapsed timer utility

CODE []  ( i addr -- addr’) INLINE[ SWAP 2* + ] NEXT, ENDCODE
CODE []! ( n i addr -- )  INLINE[ SWAP 2* + ! ] NEXT, ENDCODE
CODE []@ ( i addr – n)    INLINE[ SWAP 2* + @ ] NEXT, ENDCODE

DECIMAL 
2000 CONSTANT SIZE

CREATE Q  SIZE CELLS ALLOT    \ make some space called Q
: FILL-Q    SIZE 0 DO  I  I Q []!  LOOP ;
: SEE-Q     SIZE 0 DO     I Q []@ . LOOP ;
: EMPTY-Q   SIZE 0 DO     I Q [] OFF  LOOP ; 

Now let’s see how our new programs perform.

 

( Inline  jpeg)

 

Performance with INLINE[] CODE Words

As we can see our little programs now run 40% faster because the core routines inside the loop are much faster. 

 

But look at the last result. This uses the assembly language word called FILL. 

This line is doing the same thing as EMPTY-Q but using every trick available for the TMS9900 CPU.  It is three times faster than using the DO/LOOP structure. So the lesson is that we can do many things to increase the speed of Forth and normally that’s fast enough. However when maximum speed is required Assembler is still fastest.

 

 


[1] This is NOT the "outer"  text interpreter that we communicate with from keyboard, but an internal routine that reads addresses and runs machine code

Attached Files


Edited by TheBF, Thu May 24, 2018 9:01 PM.


#90 D-Type OFFLINE  

D-Type

    Space Invader

  • 17 posts
  • Location:Zürich

Posted Fri May 25, 2018 4:55 PM

At some point in my Vectrex 6809 Camel Forth adventure, I'm going to need these optimisations, thanks for posting.

Originally, Vectrex carts were 4k, later ones were 8k. More recent homebrew carts have been up to 64k via simple 32k bank switching.

Memory size isn't a problem any more, but program speed always is. The Vectrex runs at 1.5MHz and so to get a flicker-free 50Hz screen update you need to get each update done in 30,000 cycles.

There are no frame buffers or separate vector generator hardware available, it's all got to be done in real time by the 6809!

#91 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Sat May 26, 2018 7:13 AM

At some point in my Vectrex 6809 Camel Forth adventure, I'm going to need these optimisations, thanks for posting.

Originally, Vectrex carts were 4k, later ones were 8k. More recent homebrew carts have been up to 64k via simple 32k bank switching.

Memory size isn't a problem any more, but program speed always is. The Vectrex runs at 1.5MHz and so to get a flicker-free 50Hz screen update you need to get each update done in 30,000 cycles.

There are no frame buffers or separate vector generator hardware available, it's all got to be done in real time by the 6809!

 

 

Glad you found it helpful.  The one thing you have going for you with 6809 I believe is that the 6809 does in-direct threading in 1 instruction.

( if memory serves me right)   Contrast that to TMS9900 which takes 3 instructions and each instruction is sucking up 20 or so cycles.

 

Some other things I have noticed in Camel Forth.  

 

There are quite a few stack operations code in Forth and many times they can be made much faster as CODE words.

 

The word HERE is  defined as  DP @     and this can make the system snappier if written as a CODE word.

 

The 99 really shows up slow code and dictionary searches were really slow. The test for that is type the numbers 1 to 10 and hit return.

This causes 10 searches through the entire dictionary.  Stock Camel Forth took about 3.5 seconds.  

 

I had to re-write FIND as a code primitive called (FIND) and then the final definition is

: FIND   LATEST @ (FIND) ;

The same test now takes less than 1 second.  These changes may be very 9900 specific however, so testing is essential.

 

B



#92 Lee Stewart ONLINE  

Lee Stewart

    River Patroller

  • 3,760 posts
  • Location:Silver Run, Maryland

Posted Sat May 26, 2018 8:32 AM

The 99 really shows up slow code and dictionary searches were really slow. The test for that is type the numbers 1 to 10 and hit return.

This causes 10 searches through the entire dictionary.  Stock Camel Forth took about 3.5 seconds.  

 

I had to re-write FIND as a code primitive called (FIND) and then the final definition is

: FIND   LATEST @ (FIND) ;

The same test now takes less than 1 second.  These changes may be very 9900 specific however, so testing is essential.

 

B

 

In fbForth 2.0, typing 0 1 2 3 4 5 6 7 8 9 happens in 0.67 s, while typing 4 5 6 7 8 9 8 7 6 5 takes 0.88 s.  The reason for the difference is that 0 1 2 3 are defined as constants and are found in the dictionary, so are faster than number conversion.  I am a little surprised that Camel99 Forth is so much slower because the dictionary search for words not found in fbForth 2.0  is 505 words!

 

INTERPRET uses -FIND :

: -FIND     ( --- false | pfa len true )  ( IS:string )
    BL WORD                       \ get next word in input stream to HERE
    HERE CONTEXT @ @ (FIND)       \ search CONTEXT vocabulary for the word
    DUP 0=                        \ did we find it?
    IF                            \ no
        DROP HERE LATEST (FIND)   \ search CURRENT vocabulary
    THEN  ;

(FIND) is indeed a code primitive.  Because of the way I wrote the ROM code for fbForth 2.0, the code for (FIND) in the spoiler may not be terribly helpful, but here it is:

Spoiler

 

...lee



#93 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Sat May 26, 2018 10:29 AM

 

In fbForth 2.0, typing 0 1 2 3 4 5 6 7 8 9 happens in 0.67 s, while typing 4 5 6 7 8 9 8 7 6 5 takes 0.88 s.  The reason for the difference is that 0 1 2 3 are defined as constants and are found in the dictionary, so are faster than number conversion.  I am a little surprised that Camel99 Forth is so much slower because the dictionary search for words not found in fbForth 2.0  is 505 words!

 

INTERPRET uses -FIND :

: -FIND     ( --- false | pfa len true )  ( IS:string )
    BL WORD                       \ get next word in input stream to HERE
    HERE CONTEXT @ @ (FIND)       \ search CONTEXT vocabulary for the word
    DUP 0=                        \ did we find it?
    IF                            \ no
        DROP HERE LATEST (FIND)   \ search CURRENT vocabulary
    THEN  ;

(FIND) is indeed a code primitive.  Because of the way I wrote the ROM code for fbForth 2.0, the code for (FIND) in the spoiler may not be terribly helpful, but here it is:

Spoiler

 

...lee

 

Brad wrote Camel Forth to use more Forth definitions and less CODE words so it would be easier to port to new machines.

The poor old 9900 really struggles with that approach.

 

Here is the original FIND word .  N= is  string comparison CODE word.

Running the search loop in Forth is much slower than doing the whole thing in code as you have and CAMEL99 now has.

: FIND   ( c-addr -- c-addr   0      if not found )
\                         xt  1      if immediate
\                         xt -1      if "normal"
                   LATEST @                    \ -- adr
                   BEGIN                       \ -- adr nfa
                    2DUP OVER C@ CHAR+         \ -- adr nfa adr nfa n+1
                    N=                         \ -- adr nfa f
                    DUP IF
                          DROP
                          NFA>LFA @ DUP        \ -- adr link link
                        THEN
                   0= UNTIL                    \ -- adr nfa  OR  adr 0
                   DUP IF
                         NIP DUP NFA>CFA       \ -- nfa xt
                         SWAP IMMED?           \ -- xt iflag
                         0= 1 OR               \ -- xt 1/-1
                       THEN ;

Here is my new (FIND) word. I made use of the large register set to feed the machine more efficiently.

 

Spoiler

Edited by TheBF, Sat May 26, 2018 10:33 AM.


#94 D-Type OFFLINE  

D-Type

    Space Invader

  • 17 posts
  • Location:Zürich

Posted Sun May 27, 2018 5:00 AM

FIND is only used when compiling, correct? If yes, I guess using a cross compiler on a PC almost exclusively, which compiles my 5k binary in a couple of seconds, means this doesn't really make a lot of difference to me.

I'm still interested, though, to try the 1 2 3...9 10 Enter test the see how fast the Vectrex 6809 does it. When I'm back from holiday...

#95 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Sun May 27, 2018 7:42 AM

FIND is only used when compiling, correct? If yes, I guess using a cross compiler on a PC almost exclusively, which compiles my 5k binary in a couple of seconds, means this doesn't really make a lot of difference to me.

I'm still interested, though, to try the 1 2 3...9 10 Enter test the see how fast the Vectrex 6809 does it. When I'm back from holiday...

 

 

It is used for compiling and can also be invoked by the word tick.  ( ' interpreting mode version  AND  ['] compiling mode version )

 

So yes, using the cross-compiler means you are running the cross-compiler's FIND in the PC.  But if you ever send text source code to the vectrex the speed of the downloads will be limited by FIND's lookup speed.



#96 Lee Stewart ONLINE  

Lee Stewart

    River Patroller

  • 3,760 posts
  • Location:Silver Run, Maryland

Posted Sun May 27, 2018 9:00 AM

It is used for compiling and can also be invoked by the word tick.  ( ' interpreting mode version  AND  ['] compiling mode version )

 

I want to be careful not to muddy the waters too much for readers, but I wish to point out that, in TI Forth and fbForth (both fig-Forth based), ' (tick) works in both interpreting and compiling modes because it is state smart.  As of the Forth-83 standard, there began a move to minimize the use of state-smart words.  Consequently, tick’s state-smart capacity was removed in favor of reducing ' to interpreting mode only and creating ['] strictly for compiling mode.  And, now, back to your regularly scheduled program...

 

...lee



#97 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Sun May 27, 2018 9:18 AM

Indexed addressing mode in Forth Arrays

 

​After playing with arrays in Forth I realized the 9900 was designed to do this in the instruction set.

​Indexed addressing is the way to do it so here is one way to use it in Forth Arrays. It is not as general purpose because the base address of the array must be embedded in the assembler code.

​This means that you must write special words for each type of access but as you can see the performance is double the Forth only solutions shown earlier.

 

Edit: removed some cut and paste mistakes

\ fastest array access using indexed address mode

INCLUDE DSK1.ASM9900.F
INCLUDE DSK1.ELAPSE.F   \ elapsed timer utility

DECIMAL
2000 CONSTANT SIZE

CREATE Q   SIZE CELLS ALLOT    \ make some space called Q

\ fetch contents of any cell in ARRAY
CODE ]Q@  ( i -- array[i]@)
        TOS  1 SLA,               \ shift R1 1 bit left (mult. By 2)
        Q (TOS) TOS MOV,          \ fetch contents of Q (TOS) to TOS
	NEXT,
ENDCODE

\ store 'n' on stack to any cell in ARRAY
CODE ]Q!  ( n index --)
       TOS  1 SLA,               \ shift TOS 1 bit left (mult. By 2)
      *SP+ Q (TOS) MOV,          \ POP 2nd stack item into address Q (TOS)
       TOS POP,                  \ refill TOS register
       NEXT,
ENDCODE

\ clear any cell in ARRAY
CODE ]Q0!  ( index --)
       TOS  1 SLA,               \ shift TOS 1 bit left (mult. By 2)
       Q (TOS) CLR,              \ Clear Q (TOS)
       TOS POP,                  \ refill TOS register
       NEXT,
ENDCODE

: FILL-Q      SIZE 0 DO  I  I ]Q!  LOOP ;
: SEE-Q       SIZE 0 DO     I ]Q@ . LOOP ;
: EMPTY-Q     SIZE 0 DO     I ]Q0!  LOOP ;

Attached Files


Edited by TheBF, Mon May 28, 2018 6:38 AM.


#98 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Thu May 31, 2018 10:10 PM

Adding LINPUT to CAMEL99 Forth

 

​As I write my instruction manual designed to assist the BASIC programmer who wants to try CAMEL99 Forth I got to the ANS Forth 94 file words. I know that new programmers sometimes struggle with using TI-BASIC's numerous file options so when I started explaining READ-FILE which takes 3 input parameters and returns 3 output parameters I wondered "What would it take to add LINPUT to the system?"

 

​Turns out not too much and I think it will be a nicer interface for a BASIC programmer to use.  

 

​Here is the code that creates LINPUT to read a file record into a counted string.

: LINPUT  ( $ handle -- )
            >R                            \ push handle onto return stack 
            DUP CHAR+   ( -- $ $+1 )      \ skip past the string's length byte
            R> SELECT                     \ pop handle, select PAB for this file
            2 FILEOP ?FILERR              \ read operation, test error#
            [PAB FBUFF] V@  SWAP [PAB RECLEN] VC@  VREAD   \ VDP data -> $
            [PAB CHARS] VC@ SWAP C!       \ update string length
;

And a little DEMO file that shows how to use LINPUT went into the manual as well.

Turns out LINPUT is a little faster than READ-FILE because it does not try to do so much.

\ Print the contents of a DV80 file
INCLUDE DSK1.ANSFILES.F    \ ANS Forth file words
INCLUDE DSK1.LINPUT.F

DECIMAL
VARIABLE #1                 \ this variable will hold the file handle
VARIABLE A$ 80 ALLOT        \ variable with 80 bytes of space

: PRINT$  ( $ -- ) CR COUNT TYPE ; 

: SEEFILE ( addr len -- )   \ Usage: S" DSK1.MYFILE" SEEFILE
       DISPLAY 80 VARI SEQUENTIAL R/O OPEN-FILE ?FILERR #1 !
       BEGIN
         A$ #1 @ LINPUT 
         A$ PRINT$
       EOF UNTIL
       #1 @ CLOSE-FILE ?FILERR
;


Edited by TheBF, Thu May 31, 2018 10:11 PM.


#99 TheBF ONLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 746 posts
  • Location:The Great White North

Posted Sat Jun 2, 2018 4:25 PM

I gotta stop playing with this thing!  :)

 

​Sound List Assembler in Forth

​Now that I have a sound list player I wanted a better way to create sound lists. The Forth way of doing this is to create some new words that do the job, a meta-language as it is sometimes called.

 

I had created a set of words to create sound bytes called HZ  DB and NOISE to control the 9919 chip.

There are also output selector words called GEN1, GEN2, GEN3, GEN4

 

I already had a VDP memory manager in the library so I made some different versions of HZ, DB, and NOISE,  that put the bytes into VDP RAM sequentially rather than sending them to the chip.

 

I created a way to count the VDP bytes that were used as they went into memory and fill in a count byte at the beginning of the string as required by the sound list format. 

These are called [[  and ]] 

 

Timing is put into the list by taking a millisecond value and dividing by 16 and compiling that number at the end of the string. The word is called MS,

 

Then all we need is a way to give sound lists a name in the Forth dictionary and what you get is a simple way to make a sound list.

 

For an example I took the PARSEC Explode sound list and translated it to SOUND assembler code.

Here is the way it looked before, where I made some Forth words to emulate Assembler byte data, but for VDP RAM.

HEX
VCREATE EXPLODE
       VBYTE 7,9F,BF,DF,E7,F0,C0,07,5
       VBYTE 1,F1,6
       VBYTE 1,F2,7
       VBYTE 1,F3,8
       VBYTE 1,F4,9
       VBYTE 1,F5,10
       VBYTE 1,F6,11
       VBYTE 1,F7,12
       VBYTE 1,F8,13
       VBYTE 1,F9,14
       VBYTE 1,FA,15
       VBYTE 1,FB,16
       VBYTE 1,FC,17
       VBYTE 1,FD,18
       VBYTE 1,FE,30
       VBYTE 1,FF,0
/VEND

And here is Sound Assembler that generates the same data

DECIMAL
SOUND: EXPLODE2            \ GEN3 controls Noise Generator Frequency
   [[ GEN1 MUTE, GEN2 MUTE, GEN3 MUTE, 
​      7 NOISE, 0 DB,
      GEN3 999 HZ, ]] 80 MS, \ Parsec used "7". Sounds same as 999 Hz. ??
   GEN4                      \ control noise generator volume
   [[  -2 DB, ]]  96 MS,
   [[  -4 DB, ]] 112 MS,
   [[  -6 DB, ]] 128 MS,
   [[  -8 DB, ]] 144 MS,
   [[ -10 DB, ]] 256 MS,
   [[ -12 DB, ]] 272 MS,
   [[ -14 DB, ]] 288 MS,
   [[ -16 DB, ]] 304 MS,
   [[ -18 DB, ]] 320 MS,
   [[ -20 DB, ]] 336 MS,
   [[ -22 DB, ]] 352 MS,
   [[ -24 DB, ]] 368 MS,
   [[ -26 DB, ]] 384 MS,
   [[ -28 DB, ]] 768 MS,
   [[ -30 DB, ]]   0 MS,
;SOUND

I kind of like sound lists now.

 

B

 

For those who might be curious here is the code.  I have to update GITHUB. All of this is not there yet.

Spoiler

Edited by TheBF, Sat Jun 2, 2018 4:32 PM.


#100 Lee Stewart ONLINE  

Lee Stewart

    River Patroller

  • 3,760 posts
  • Location:Silver Run, Maryland

Posted Sat Jun 2, 2018 5:03 PM

You are moving right along!  I see that I need to explore how I might similarly compose sound lists/tables in fbForth 2.0.  I am still in slow motion with physical therapy and rest taking up far more time than I would like.

 

...lee







Also tagged with one or more of these keywords: Camel99, Forth, Concatentive Programming, ANS Forth

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users