Jump to content
IGNORED

TI-Forth-to-fbForth-3.0


Recommended Posts

@Lee Stewart

 

  What I know about Forth, can fit in a sewing thimble.

  Back in the 80's, the TI Hoosier's User Group, had this really good programmer, named Greg Goodwin. He wrote a program call Kibbit.

  I can start fbForth on Classic99, is can I just copy this program in to fbForth in Classic99 and expect it to run?

 

84:07:04. Kibbit instructions
by Greg Goodwin
Kibbit is a TI Forth graphics program which draws from the keyboard or joysticks. Please note: This is a revised version of the Kibbit program which is saved on the Forth demo disk in the HUGger library.

 

The key functions of Kibbit are:
CR - Clears the current work screen.
SPACEBAR Aborts program.
Fire Button (or 0) Toggles graphics modes. A sprite will appear on the tip of the line. The letter is the current mode.
D Draw
U Undraw
T Dtog (if line undrawn else draw one.)
Either joystick or keys may be used in drawing (make sure the ALPHA LOCK is up!).
If you have any problems getting this version to run, leave me a message on the HUGbbs or through the users group PO Box (also let me know what you think of it). A future version will include the saving of screens, and mixing with user programs.

 

Forth … write … Greg.
Kibbit revised listing ( Kibbit by G. Goodwin)

 

50 VARIABLE JOY 50 VARIABLE JRT 0 VARIABLE SELECT
HEX 3800 SSDT : INIT_TURTLE
8050 2828 2828 1000 8A SPCHAR
8040 2424 2424 1800 8B SPCHAR
8040 201C 0808 0800 8C SPCHAR 22 22 5 8C 1 SPRITE ;
DECIMAL : KIBBIT INIT_TURTLE GRAPHICS2 BEGIN
1 JOYST CASE 04 OF -1 JOY +! ENDOF 252 OF 1 JOY +! END OF ENDCASE
CASE 04 OF 1 JRT +! ENDOF 252 0F -1 JRT +! ENDOF ENDCASE
18 = IF 1 SELECT +1 ENDIF SELECT @ CASE
0 OF DRAW 138 1 SPRPAT ENDOF
1 OF UNDRAW 139 1 SPRPAT ENDOF
2 OF DTOG 140 1 SPRPAT ENDOF
3 OF 0 SELECT ' ENDOF ENDCASE JRT @ JOY @ 1 SPRPUT
JRT @ JOY @ DOT ?KEY 13 = IF GRAPHICS 2 ENDIF
? KEY 32 = UNTIL TEXT ;
KIBBIT ;S

 

  • Like 3
Link to comment
Share on other sites

Posted (edited)

Here is the code expanded for easier reading with corrections and some explanation:

 

50 VARIABLE JOY      \ joystick y position
50 VARIABLE JRT      \ joystick x position
 0 VARIABLE SELECT   \ selection
HEX 
\ Set Sprite Descriptor Table to 3800h in VRAM <--CANNOT do in text modes!
\ 3800 SSDT       <--already done by GRAPHICS2 in fbForth
: INIT_TURTLE
   \ set bitmap mode before sprites
   GRAPHICS2         \ clears SDT
   \ initialize turtle sprite chars
   8050 2828 2828 1000 8A SPCHAR
   8040 2424 2424 1800 8B SPCHAR
   8040 201C 0808 0800 8C SPCHAR
   \ initialize turtle sprite
   22 22 5 8C 1 SPRITE ;
DECIMAL 
: KIBBIT
   INIT_TURTLE
   BEGIN
      1 JOYST CASE      \ y value
         04 OF -1 JOY +! ENDOF
         252 OF 1 JOY +! ENDOF
      ENDCASE
      CASE              \ x value
         04 OF 1 JRT +! ENDOF
         252 OF -1 JRT +! ENDOF
      ENDCASE
      18 = IF           \ fire button?
         1 SELECT +!    \ increment selection
      ENDIF
      SELECT @ CASE
         0 OF DRAW 138 1 SPRPAT ENDOF
         1 OF UNDRAW 139 1 SPRPAT ENDOF
         2 OF DTOG 140 1 SPRPAT ENDOF
         3 OF 0 SELECT ! ENDOF
      ENDCASE
      JRT @ JOY @ 1 SPRPUT    \ move turtle to current position
      JRT @ JOY @ DOT         \ draw/undraw/toggle a dot at current position
      ?KEY 13 = IF      \ CR?
         INIT_TURTLE    \ set bitmap mode/re-initialize turtle to clear screen
      ENDIF
      ?KEY 32 =         \ <space>?
   UNTIL
   TEXT ;               \ back to text mode
KIBBIT            \ start program
;S                \ stop scanning block

 

You can almost drop the original into fbForth—very little change—mostly correction of typos or missed OCR.

 

The above, corrected code can be dropped right in. You do not need the ;S . That was used to tell the interpreter to stop scanning the block for more code—saves time when loading from floppy.

 

...lee

Edited by Lee Stewart
clarification
  • Like 5
Link to comment
Share on other sites

3 hours ago, dhe said:

 

  What I know about Forth, can fit in a sewing thimble.

Well you know @dhe , Forth is like smoking.

It's never too late to start! :) 

 

Also it's pretty cool that with FbForth you have a much better TI-Forth that just works.

 

(Of course now I have to see how and if I can do that clever little program with my system. LOL)

 

  • Like 4
Link to comment
Share on other sites

4 hours ago, dhe said:

Thanks @Lee Stewart,

    I've only ever seen screens like the original KIBBIT listing.

 

    Your formatted, and of course corrected and commented version is much more approachable.

 

image.png.b3e919cd88223f41d6e4f566e11aa67e.png

 

Don’t forget the W,R,Z,C keys for the diagonal directions.

 

...lee

  • Like 1
  • Haha 1
Link to comment
Share on other sites

Hi Lee,

  I'm about a quarter of the way through the fbforth v2 manual.

 

Would you mind walking me through, a simple program that would:

   Set the display to graphics mode

   Get my name

   Print - Hello, $Name

   and launch a balloon sprite from the bottom of the screen like it's floating up?

  • Like 1
Link to comment
Share on other sites

53 minutes ago, dhe said:

Hi Lee,

  I'm about a quarter of the way through the fbforth v2 manual.

 

Would you mind walking me through, a simple program that would:

   Set the display to graphics mode

   Get my name

   Print - Hello, $Name

   and launch a balloon sprite from the bottom of the screen like it's floating up?

I am not an expert on FbForth, but I used TI Forth for a long time so I can get you started until Lee gets online. 

 

Video modes in the system are controlled so simply.

Just use their name:

TEXT             40 column

GRAPHICS     32 column a la BASIC 

GRAPHCS2     bit map mode 

SPLIT    which gives you bit map on the top 2/3 of the screen and a windows of GRAPHICS mode on the bottom. (cool)

 

"Get my name" 

This is not as simple as BASIC, and from my review of the FbForth doc,  it is not obvious to me

the best way to do this in FbForth, so I am going to wait for Lee.

 

To make a sprite at the bottom of the screen go into GRAPHICS mode 

 

GRAPHICS 

 

And then define the sprite and it's motion vector 

( dotcol dotrow color char spr# )
  127     180     7    42   1 SPRITE   
  
(  x   y  spr# )
   0  -3  1  MOTION  

 

Then we need to tell the system how many sprites will automatically move.

Since sprites numbers are 0 ..31  and we want sprite 1 to move, we need to say we want 2 sprites to have automotion. ( 0 and 1 )

 

2 #MOTION 

 

And off it goes... 

 

Notice we can play with sprites interactively to see how they will work 

 

Try 

0  -10 1 MOTION 

 

  • Like 3
Link to comment
Share on other sites

In terms of Forth programming style, if we were doing a project we would not use literal numbers for parameters where names would be better. 

 

So you might want to make your sprites have familiar names. 

 

0 CONSTANT #0 

1 CONSTANT #1 

2 CONSTANT #2 

 

And colors are easier to remember by name. 

Here is a little trick invented by the late Neil Baud.  

Put this code in a BLOCK with the FbForth Editor and you can LOAD it anytime you need it. 

\ do it yourself enumeration
: ENUM  ( 0 <text> -- n) DUP CONSTANT  1+ ;

0 ENUM TRANS     ENUM BLACK    ENUM MEDGRN
  ENUM LTGRN     ENUM DKBLU    ENUM LTBLU
  ENUM DKRED     ENUM CYAN     ENUM MEDRED
  ENUM LTRED     ENUM DKYEL    ENUM LTYEL
  ENUM DKGRN     ENUM MAGENTA  ENUM GRAY
  ENUM WHITE
DROP

 

And if you defined ENUM then of course you could use it for those sequential sprite numbers too. 

That's all for now. 

  • Like 3
Link to comment
Share on other sites

3 hours ago, dhe said:

Hi Lee,

  I'm about a quarter of the way through the fbforth v2 manual.

 

Would you mind walking me through, a simple program that would:

   1. Set the display to graphics mode

   2. Get my name

   3. Print - Hello, $Name

   4. Launch a balloon sprite from the bottom of the screen like it's floating up?

 

Certainly!

 

5 hours ago, dhe said:

1. Setting to graphics mode

 

The GRAPHICS word sets graphics mode, clears the screen, and moves system tables if necessary. It can be part of another word, but should usually be ahead of anything you want persisted on the screen.

 

5 hours ago, dhe said:

2. Get my name

 

Many ways to do this. Here is one:

\ Variable MYNAME with 20 as the character count at the beginning.
\ Total of 24 bytes allowed, with the leading word and the 22 ALLOTed bytes.
HEX 1400 DECIMAL VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "         \ prompt for name
   MYNAME 1+ 20 EXPECT     \ start 1 byte after start of MYNAME..get up to 20 chars
;

 

The trouble with this is that EXPECT adds 2 nulls after the input and, if you do not correct the character count at the beginning of MYNAME , doing the following to type the name will print 20 chars including the 2 nulls (ASCII 0) and whatever follows them, which is likely not what you want:

MYNAME COUNT TYPE

 

We could add code to GETNAME to count the actual number of chars typed and store that at the beginning of MYNAME to get the correct length:

HEX 1400 DECIMAL VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME               \ start of MYNAME
   BEGIN      \ count actual chars
      1+                \ increment address
      DUP               \ keep a copy for next go round
      C@ 0=             \ get char..is it 0?
   UNTIL
   MYNAME -             \ subtract the 2 addresses to get char count + 1
   1-                   \ correct to actual char count
   MYNAME C!            \ store char count at start of MYNAME
;

 

There are certainly other ways to do this. Perhaps you can suggest some.

 

...lee

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Here is another GETNAME identical with the last one but a bit more concise by using COUNT to retrieve the next byte and increment to string address:

 

: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME 1+            \ start of MYNAME string after length byte
   BEGIN      \ count actual chars
      COUNT             \ get next byte..increment address..addr byte to stack
      0=                \ retrieved char = 0?
   UNTIL
   MYNAME -             \ subtract the 2 addresses to get char count + 2
   2-                   \ correct to actual char count
   MYNAME C!            \ store char count at start of MYNAME
;

 

...lee

Edited by Lee Stewart
comment correction
  • Like 2
Link to comment
Share on other sites

@Lee Stewart posted the following to me:

 

Q: How do I set graphics mode?

A: The GRAPHICS word sets graphics mode, clears the screen, and moves system tables if necessary. It can be part of another word, but should usually be ahead of anything you want persisted on the screen.

 

Q: How do I get my name?

A: Many ways to do this. Here is one:

\ Variable MYNAME with 20 as the character count at the beginning.
\ Total of 24 bytes allowed, with the leading word and the 22 ALLOTed bytes.
HEX 1400 DECIMAL VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "         \ prompt for name
   MYNAME 1+ 20 EXPECT     \ start 1 byte after start of MYNAME..get up to 20 chars
;

 

The trouble with this is that EXPECT adds 2 nulls after the input and, if you do not correct the character count at the beginning of MYNAME , doing the following to type the name will print 20 chars including the 2 nulls (ASCII 0) and whatever follows them, which is likely not what you want:

MYNAME COUNT TYPE

 

We could add code to GETNAME to count the actual number of chars typed and store that at the beginning of MYNAME to get the correct length:

HEX 1400 DECIMAL VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME               \ start of MYNAME
   BEGIN      \ count actual chars
      1+                \ increment address
      DUP               \ keep a copy for next go round
      C@ 0=             \ get char..is it 0?
   UNTIL
   MYNAME -             \ subtract the 2 addresses to get char count + 1
   1-                   \ correct to actual char count
   MYNAME C!            \ store char count at start of MYNAME
;

 

Q: How do I print Hello, $NAME

A:

: HELLO
   ." Hello, "          \ print greeting
   MYNAME               \ address of MYNAME
   COUNT                \ get char count and address after it
   TYPE                 \ type MYNAME string as part of greeting
;

 

Here is another GETNAME identical with the last one but a bit more concise by using COUNT to retrieve the next byte and increment to string address:

: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME 1+            \ start of MYNAME string after length byte
   BEGIN      \ count actual chars
      COUNT             \ get next byte..increment address..addr byte to stack
      0=                \ retrieved char = 0?
   UNTIL
   MYNAME -             \ subtract the 2 addresses to get char count + 1
   2-                   \ correct to actual char count
   MYNAME C!            \ store char count at start of MYNAME
;

 

 

Thanks a million Lee, I'm still working through these for comprehension! {It might be a while}

  • Like 2
Link to comment
Share on other sites

4 hours ago, dhe said:

4. Launch a balloon sprite from the bottom of the screen like it's floating up?

 

HEX
\ Array of 4 character definitions for magnified balloon
DATA[ 0F1F 3F7F 7F7F 7F3F
      1F0F 0702 0202 0101
      F8FC FEFF FFFF FFFE
      FCF8 F0A0 A0A0 C0C0 ]DATA  \ leaves address and cell count on stack
80 SPDCHAR        \ assign above char defs to sprite chars 80h..83h (128..131)
2 MAGNIFY                  \ magnification = 2
0A 0B0 6 80 0 SPRITE       \ sprite 0: char 128/dark red/dotrow=176/dotcol=10
3 -6 0 MOTION              \ sprite 0 motion
1 #MOTION                  \ set sprites < 1 in motion

 

Try it with

3 MAGNIFY                  \ magnification = 3

 

There is a lot more you can do with this, so think about exactly what it is you want to happen and we can work through it.

 

...lee

  • Like 2
Link to comment
Share on other sites

Posted (edited)

When I see someone interested in learning Forth I have an overwhelming urge to help them get through stuff that took me too much time. 

So here goes...

 

I would make one suggestion about a "rule of thumb" as we say in English,  for Forth. 

The rule is "Don't hide your tools".

 

It means extract good pieces of code into a word so you can reuse it for other parts of the program.

 

Lee made a very clever piece of code that finds the end of a zero delimited string.

So let's extract it and make it a word. 

: $END  ( addr1 -- addr1 addr2 ) DUP BEGIN  COUNT  0= UNTIL ;

 

When we have a start address and an end address on that data stack we can find the length very easily

 OVER - 


We can put these ideas together to make something like a BASIC input statement, but it only works with strings.

: $INPUT ( addr1 len -- )
          \ automate the adjustment to hold a length byte 
           OVER 1+  SWAP      ( -- addr1 addr' len ) 
           EXPECT  $END       ( -- addr1 addr2 ) 
           OVER -             ( -- addr length)  \ compute the length
           2-                \ correct the count  
           SWAP C!           \ store length in the first byte of the address
;           


 

And in case you don't need to reserve permanent space for a specific string let me introduce PAD.

PAD  is typically located some distance past the end of the dictionary, in un allocated memory.

It's free to use but know that it could be overwritten by compiling new code or even another word in the system.

Caveat emptor.

 

I would add another word as well if you plan to use "byte-counted" strings which is common in forth.

"dot" prints a number  so here .$  print a byte counted string. 

 

: .$   COUNT TYPE ;   ( this is a normal practice in forth to make a small sub-routine. 

 

So with PAD and $INPUT and .$  Lee's example becomes:

 

: GETNAME   

    CR ." What's your name? "  PAD 32 $INPUT      

    CR ." Hello " PAD .$   ;

 

:) 

 

 

 

Edited by TheBF
Wrong comment
  • Like 3
  • Thanks 1
Link to comment
Share on other sites

4 hours ago, TheBF said:

: .$   COUNT TYPE ;   ( this is a normal practice in forth to make a small sub-routine.

 

Careful here. In fbForth and TurboForth, an almost identical word ( $. ) types the number on the top of the stack as an unsigned, hexadecimal number.

 

...lee

  • Like 1
  • Thanks 2
Link to comment
Share on other sites

1 minute ago, Lee Stewart said:

 

Careful here. In fbForth and TurboForth, an almost identical word ( $. ) types the number on the top of the stack as an unsigned, hexadecimal number.

 

...lee

Good point. Well we could always call it $PRINT. 

I find I get tired typing COUNT TYPE endlessly. 

 

  • Like 1
Link to comment
Share on other sites

Posted (edited)

OK...Here, in the spoiler below, are all the above (1)..(4) requested HOW-TOs together with some helper words and a final program word to run:

 

Spoiler
DECIMAL 
\ Variable MYNAME with room at the beginning for a length byte. Total
\ of 24 bytes allowed, with the leading word and the 22 ALLOTed bytes.
0 VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME 1+            \ start of MYNAME string after length byte
   BEGIN      \ count actual chars
      COUNT          \ get next byte..increment address..addr & byte to stack
      0=             \ retrieved char = 0?
   UNTIL
   MYNAME -          \ subtract the 2 addresses to get char count + 2
   2-                \ correct to actual char count
   MYNAME C!         \ store char count at start of MYNAME
;
: HELLO
   ." Hello, "       \ print greeting
   MYNAME            \ address of MYNAME
   COUNT             \ get char count and address after it
   TYPE              \ type MYNAME string as part of greeting
   ." !"             \ end greeting with '!'
   CR                \ cursor to next line
;
HEX
: SPRITE0
   \ Array of 4 character definitions for magnified balloon
   DATA[ 0F1F 3F7F 7F7F 7F3F
         1F0F 0702 0202 0101
         F8FC FEFF FFFF FFFE
         FCF8 F0A0 A0A0 C0C0 ]DATA  \ leaves address and count on stack
   80 SPDCHAR  \ assign above char defs to sprite chars 80h..83h (128..131)
   2 MAGNIFY               \ magnification = 2
   0A 0B0 6 80 0 SPRITE    \ sprite 0: char 128/dark red/dotrow=176/dotcol=10
   3 -6 0 MOTION           \ sprite 0 motion
;
DECIMAL
: ANYKEY
   KEY DROP       \ wait for a key and drop it
;
: STARTPROMPT
   CR CR ." ...any key to start "
   ANYKEY
;
: STOPPROMPT
   CR CR CR ." ...any key to stop "
   ANYKEY
;
\ Main program
: DOSTUFF
   VDPMDE @       \ get current screen mode for restoration at end
   GRAPHICS       \ set graphics mode, clearing screen and homing cursor
   SPRITE0        \ set up sprite 0 and display it
   CR CR          \ skip 2 lines
   GETNAME        \ get user's name
   STARTPROMPT
   PAGE           \ clear screen and home cursor
   HELLO          \ greet user
   1 #MOTION      \ set sprite 0 in motion
   STOPPROMPT
   VMODE          \ restore screen mode
;
CR CR ." ...type DOSTUFF <enter> to run"

 

 

Of course, there are other ways to do all of this. You should have no trouble incorporating @TheBF’s solutions into the above, as well.

 

...lee

Edited by Lee Stewart
clarified first lines of code
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

I remember struggling to figure out how to get keyboard input in TI Forth when I coded Core Wars. I no longer recall how I did it, but it did strike me at the time that Forth did not have such a fundamental function built-in... Any particular reason for this? Not exactly a user friendly omission I might add...

https://youtu.be/ZFANT61hEF0?si=1seXzWQpz9zOR7PR

  • Like 2
Link to comment
Share on other sites

2 hours ago, Vorticon said:

I remember struggling to figure out how to get keyboard input in TI Forth when I coded Core Wars. I no longer recall how I did it, but it did strike me at the time that Forth did not have such a fundamental function built-in... Any particular reason for this? Not exactly a user friendly omission I might add...

The guy who invented Forth, Chuck Moore, decided that he could never predict what he needed for any given project so he made himself a toolkit with which to build whatever he wanted.

His credo is best described as radical minimalism.  

 

This is a guy who ported his multitasking Forth system to the IBM 360, before the 360 had an Operating system,  in a couple of days. 

At the end of the week he had the machine doing things the IBM engineers didn't know it could do. :) 

So a different kind of mind. 

 

To your point FigForth is a bit obtuse in this area. There are inconsistencies in it that have been eliminated in modern Forth.

Like EXPECT creating a zero delimited string.  Those are 'C' style strings and Forth typically uses Pascal style byte-counted strings everywhere else. huh? 

 

ANS Forth removed EXPECT and gave us ACCEPT ( addr len -- len)  which is still at the "tool" level but at least with an extra DUP, it returns the address and length of the string you typed. :) 

 

So the short answer to your question is because Forth is not a language but a toolkit to build the language that you need for your current project. 

That's hard for people used to "languages" to get their head around.

 

By example I replicated TI BASIC's "INPUT"  functionality for myself and true to Chuck's philosophy, one word does one thing.

These words don't take input from files.

That would make them needlessly complicated if I only need input from the keyboard.

 

Chuck is fond of saying he doesn't write general solutions because nobody has every told him what the "general problem" is. :) 

 

Here are my TI BASIC style input word for strings using ACCEPT

DECIMAL
: $ACCEPT ( $addr -- ) CR ." ?  "  DUP  1+ 80 ACCEPT  SWAP C!  ;

: $INPUT  ( $addr -- ) BEEP $ACCEPT ;  \ BEEP like TI-BASIC

 

And here is one for numbers that does the HONK and loops until you satisfy it 

: #INPUT  ( variable -- )   \ made to look/work like TI-BASIC
          BEEP
          BEGIN
            PAD $ACCEPT    \ $ACCEPT text into temp buffer PAD
            PAD COUNT NUMBER?  \ convert the number in PAD
          WHILE              \ while the conversion is bad we do this
             CR HONK ." input error "
             CR DROP
          REPEAT
          SWAP ! ;    \ store the number in the variable on the stack)

 

Now the truth... I don't think I have ever used them in a program as is.

I build something better for the requirement at hand with the toolkit. 

 

As my Anglican friends would say: "Thus endeth the lesson" 

 

  • Like 2
  • Thanks 2
Link to comment
Share on other sites

10 hours ago, Lee Stewart said:

OK...Here, in the spoiler below, are all the above (1)..(4) requested HOW-TOs together with some helper words and a final program word to run:

 

  Hide contents
DECIMAL 
\ Variable MYNAME with room at the beginning for a length byte. Total
\ of 24 bytes allowed, with the leading word and the 22 ALLOTed bytes.
0 VARIABLE MYNAME 22 ALLOT
: GETNAME
   ." Your name? "      \ prompt for name
   MYNAME 1+ 20 EXPECT  \ start 1 byte after start of MYNAME..up to 20 chars
   MYNAME 1+            \ start of MYNAME string after length byte
   BEGIN      \ count actual chars
      COUNT          \ get next byte..increment address..addr & byte to stack
      0=             \ retrieved char = 0?
   UNTIL
   MYNAME -          \ subtract the 2 addresses to get char count + 2
   2-                \ correct to actual char count
   MYNAME C!         \ store char count at start of MYNAME
;
: HELLO
   ." Hello, "       \ print greeting
   MYNAME            \ address of MYNAME
   COUNT             \ get char count and address after it
   TYPE              \ type MYNAME string as part of greeting
   ." !"             \ end greeting with '!'
   CR                \ cursor to next line
;
HEX
: SPRITE0
   \ Array of 4 character definitions for magnified balloon
   DATA[ 0F1F 3F7F 7F7F 7F3F
         1F0F 0702 0202 0101
         F8FC FEFF FFFF FFFE
         FCF8 F0A0 A0A0 C0C0 ]DATA  \ leaves address and count on stack
   80 SPDCHAR  \ assign above char defs to sprite chars 80h..83h (128..131)
   2 MAGNIFY               \ magnification = 2
   0A 0B0 6 80 0 SPRITE    \ sprite 0: char 128/dark red/dotrow=176/dotcol=10
   3 -6 0 MOTION           \ sprite 0 motion
;
DECIMAL
: ANYKEY
   KEY DROP       \ wait for a key and drop it
;
: STARTPROMPT
   CR CR ." ...any key to start "
   ANYKEY
;
: STOPPROMPT
   CR CR CR ." ...any key to stop "
   ANYKEY
;
\ Main program
: DOSTUFF
   VDPMDE @       \ get current screen mode for restoration at end
   GRAPHICS       \ set graphics mode, clearing screen and homing cursor
   SPRITE0        \ set up sprite 0 and display it
   CR CR          \ skip 2 lines
   GETNAME        \ get user's name
   STARTPROMPT
   PAGE           \ clear screen and home cursor
   HELLO          \ greet user
   1 #MOTION      \ set sprite 0 in motion
   STOPPROMPT
   VMODE          \ restore screen mode
;
CR CR ." ...type DOSTUFF <enter> to run"

 

 

Of course, there are other ways to do all of this. You should have no trouble incorporating @TheBF’s solutions into the above, as well.

 

...lee

I love ANYKEY.   

 

Reminds me of the help desk story about the lady who called in and said :

 

"The computer is saying press any key to continue, but I can't find the 'any" key on the keyboard"  😂

 

  • Like 1
  • Haha 2
Link to comment
Share on other sites

OK this took me a hell of a lot longer to port to Camel99 Forth. I had never dealt with sprites in my experiments with bit mapped mode.

So I had to work on the GRAPHICS2 library, then I had to write a new sprite library to handle GRAPHICS2 mode but it was a good exercise for me. 

I was totally shamed by how simple it was to drop the TI-Forth version, with a few corrections into FbForth. 

 

Anyway I had little better to do this week. :) 

 

I wanted our Forth neophyte to notice some differences in my version  versus the TI-FORTH version. ( @dhe ) 

  1.  My program has no variables. Crazy right?  But Forth has a bit in common with functional languages where instead of storing data in variable you generate it and leave it on the data stack for somebody to use. 
    The older version IMHO, was written by someone who came from BASIC and then wrote a kind of BASIC program, but using Forth keywords. 
    It takes some time to get your head around programming in Forth "style" and everybody seems to do it a bit different. 
     
  2.  The program is broken up into small pieces which makes testing easier.
    That's important in Forth because the verdammt language is hard enough so you need to test as you go so you trust the pieces. 
     
  3. The small sub-routine style would kill normal languages because you have to transfer data in and out of variables. Forth was made with the data stack so sub-routine overhead is lower. 
    It's not free, but it is quite efficient. 

 

Here is what I came up with.  I added some nicer cursors and a pen-up ability. 

 

Spoiler
\ KIBBIT.FTH   May 31 2024 ported to Camel99 Forth 

\ Originally written by:
\ Greg Goodwin, TI Hoosier's User Group, circa 1980s

\ Translated to Camel99 Forth 
NEEDS .S     FROM DSK1.TOOLS   \ needed for debugging only 
NEEDS CASE   FROM DSK1.CASE 
NEEDS PLOT   FROM DSK1.GRAPHICS2 
NEEDS SPRITE FROM DSK1.SPRITES2   ( for use with Graphics2)
NEEDS JOYST  FROM DSK1.JOYST


HEX 
\ ================ KIBBIT BEGINS HERE =====================

\ define the sprite shape data but give them a name
CREATE $PENCIL ( -- addr ) 8060 , 7038 , 1C0E , 0400 ,
CREATE $ARROW  ( -- addr ) F0E0 , E090 , 0804 , 0000 ,
CREATE $ERASER ( -- addr ) 0010 , 387C , 3E1E , 0C00 ,
CREATE $BRUSH  ( -- addr ) 8080 , C060 , 6010 , 0800 ,
CREATE $ROLLER ( -- addr ) 007E , 7E02 , 1E10 , 1010 ,

DECIMAL
: INIT_KIBBIT
   GRAPHICS2    \ set bitmap mode before anything else 
   DELALL       \ INIT the sprite memory 

\ Write turtle sprite char data into VDP sprite definition table
\  data   bytes char 
   $PENCIL 8    138 SP.SHAPE
   $ERASER 8    139 SP.SHAPE
   $ROLLER 8    140 SP.SHAPE
   $ARROW  8    141 SP.SHAPE 

    1 15 COLOR 
\   colr char  X  Y spr#    
     5   138  22 22  0 SPRITE ;

\ JOYST Output decoding 
HEX 
 01 CONSTANT Fire
 02 CONSTANT Left
 04 CONSTANT Right
 08 CONSTANT Down
 10 CONSTANT Up
 0A CONSTANT Down/left
 0C CONSTANT Down/right
 12 CONSTANT Up/left
 14 CONSTANT Up/right

DECIMAL 
\ add byte to a byte in VDP memory "vdp char plus store"
: VC+!  ( byte Vaddr -- ) DUP>R VC@ +  R> VC! ;

0 CONSTANT #1  \ the sprite name 

\ these words alter the sprite position by changing the fields in VDP memory 
: GOUP     -1 #1 SP.Y VC+! ; 
: GODOWN    1 #1 SP.Y VC+! ;
: GOLEFT   -1 #1 SP.X VC+! ;
: GORIGHT   1 #1 SP.X VC+! ;

: MOVE_BRUSH 
    0 JOYST 
    CASE 
        Left  OF  GOLEFT         ENDOF
        Right OF  GORIGHT        ENDOF
        Down  OF  GODOWN         ENDOF
        Up    OF  GOUP           ENDOF

    Down/left OF  GODOWN GOLEFT  ENDOF 
   Down/right OF  GODOWN GORIGHT ENDOF 
    Up/left   OF  GOUP   GOLEFT  ENDOF 
    Up/right  OF  GOUP   GORIGHT ENDOF 
    ENDCASE  
;

\ common factor 
: ISCURSOR  ( ascii -- ) #1 SP.PAT VC! ; 

: USE-PENCIL   PENCIL IS STYLUS   138 ISCURSOR ; 
: USE-ERASER   ERASER IS STYLUS   139 ISCURSOR ;
: USE-ROLLER   BRUSH  IS STYLUS   140 ISCURSOR ; 
: USE-ARROW    PENUP  IS STYLUS   141 ISCURSOR ;

: CHANGE_BRUSH 
    KEY? 
    CASE
      [CHAR] D OF  USE-PENCIL    ENDOF  \ pen down to draw 
      [CHAR] E OF  USE-ERASER    ENDOF 
      [CHAR] T OF  USE-ROLLER    ENDOF 
      [CHAR] U OF  USE-ARROW     ENDOF  \ pen up 
      [CHAR] C OF  INIT_KIBBIT   ENDOF 
    ENDCASE   
;

: KIBBIT
   INIT_KIBBIT  
   USE-ARROW 
   BEGIN
     #1 POSITION PLOT 
     MOVE_BRUSH 
     CHANGE_BRUSH
     ?TERMINAL   
   UNTIL
   TEXT ;  

\ KIBBIT    \ to start program

 

 

Here' me showing that it still needs work to be practical :)

 

 

  • Like 2
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...