Jump to content
IGNORED

Forth Tutorials


matthew180

Recommended Posts

OK I have a few more questions:

 

Since most programs will span more than one screen, how does one load all the screens at once?

 

Yes. Use the word --> at the point on the screen/block where you want to load the next screen/block. This would normally be the last item on the page; but, there are reasons for ignoring the remainder of a screen/block. You can also explicitly load a particular screen/block with 67 LOAD if screen/block 67 is the next block you wish loaded. For obvious reasons, --> is usually better.

 

Also, when I edit a particular screen, I have to reload it and as expected I then get a string of redefined warnings. Is there another way to do this?

 

If you FORGET the first definition on the screen in question, you will erase all the definitions from the one you FORGET to the latest one defined and, thus, avoid the problem. By first definition, I mean to include constants, variables and anything else that is compiled into the dictionary.

 

Finally, I'm not completely clear on SMLIST and SPRMOV:

 

0 -2 0 SMLIST should set up a movement vector straight up for sprite 0

0 1 SPRMOV should move ONLY sprite 0 according the its previously defined SMLIST vector

Am I correct so far? Now if I change SMLIST, do I need to issue another SPRMOV or does the sprite simply change direction and/or velocity?

 

It seems that you expect SPRMOV to set sprites into automotion. It won't. It only moves them according to vectors set up by SMLIST. Consequently, setting up different vectors will not take effect until you issue another SPRMOV for the range of sprites you wish to move.

I am pretty sure @Willsy has not implemented sprite automotion. It wasn't obvious to me from a cursory look at TI Forth what would be needed to implement automotion in TF. To simulate automotion, you will need to set up SPRMOV in a loop. As I recall, most gamers prefer that to automotion anyway.

 

As you might have guessed, I'm having problems getting sprites to move and I wanted to double check that I understood the above words correctly...

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Hi,

 

Yes Lee, you're right. TF doesn't have sprite automotion. That will come as a surprise to anyone coming from the XB world, as it is a crutch upon one must rely if one is to use sprites in XB. Anyone used to assembly (I know you are, Vorticon!) will be quite happy moving sprites around under their own control, and enjoy the extra flexibility that comes with it. We're all familiar with sprite over-shoot and dodgy collision detection in XB.

 

In TF, the sprites move on their vectors only when SPRMOV is executed. The more often you execute SPRMOV, the more often your sprites will move.

 

If you arrange your sprites cleverly, you can move them in groups, and get the same effect as automotion when calling SPRMOV in a loop. This is possible because SPRMOV takes a starting sprite parameter. So you could move, say, sprites 0 to 3 on continuously in a loop, and every other loop iteration, execute an extra SPRMOV on sprites 4 to 7, for example.

 

OR, you can set say, sprites 0 to 3 to move, say, 4 pixels to the right, and sprites 4 to 7 to move 2 pixels to the right, and call SPRMOV on all 8 sprites, and the first four will move at twice the rate of the second four. It's up to you. You're in control :). For an example of SPRMOV in action, see this page (scroll down to the sprite demo - it looks a bit jerky, but that's just YouTube).

 

Regarding dictionary re-definitions, as Lee says, FORGET is your friend here.

 

Say you have block 43, and it has the following definitions in it:

 

: MoveUp .... ;

: MoveDown ... ;

: MoveLeft ... ;

: MoveRight ;

-->

 

(Note that the --> in the above causes the next block to be loaded - you 'chain' blocks together in this way)

 

As you have found out, you get re-definition warnings when reloading the block. The way around this is to do:

 

FORGET MoveUp

: MoveUp .... ;

: MoveDown ... ;

: MoveLeft ... ;

: MoveRight ;

-->

 

When the FORGET MoveUp is executed, MoveUp, *and everything AFTER it* is removed from the dictionary. The fact that your blocks are chained re-loads the stuff that was removed from the dictionary. Note that FORGET (as stated in the language reference on the TF site) cannot be used inside a colon definition.

 

After a while, continually editing and re-loading blocks (and waiting for the subsequent blocks to be re-compiled) will get on your nerves (It's fine if you have a RAM disk). Well, there is an alternative method, which is very very handy when you are just entering colon definitions at the command line and feeding it stack data and trying out/debugging the definition. It means that you don't have to re-load all the stuff *after* the word you are working on. It's a trick, for sure, but it *does* save time while debugging a word. When you have the word working nicely, you edit your block accordingly, use FORGET and re-compile (or, as I do, use COLD to restart the whole shebang and compile afresh).

 

One last note regarding FORGET. Forget removes the FIRST matching occurrence that it finds. All dictionary searches start from the last defined word and work backwards. So:

 

: TEST 1 . ;

: TEST 2 . ;

: TEST 3 . ;

FORGET TEST

TEST

 

Can you work out what happens here?

 

Finally, have a look at MARKER. MARKER isn't built in to TF, but is very easily defined. I haven't got around to putting it on the site, but I've attached information for you.

 

MARKER.txt

 

I guess all the above is a lot to digest. Don't worry. Small steps. Rome wasn't built in a day. You're immersing yourself in a programming language that is so very very different to anything else, with bugger all documentation! As I like to say to people, when learning Forth, it's better to leave your previous programming experience 'baggage' behind... It'll just weigh you down :grin:

Link to comment
Share on other sites

Just had a thought regarding ED: and ;ED.

 

I'm not sure which build of TF V1.2 you're running, but you might find that it doesn't work if you are using the (I think) the last two builds of V1.2. The reason is because BRANCH and 0BRANCH were changed to take an explicit address, rather than an offset (makes it slightly faster). The code published uses an offset. I'll change the code to produce an explicit address (ED: will get simpler, less code!).

 

Mark

Link to comment
Share on other sites

Couldn't resist... The new version of ED for V1.2 is (I think):

 

: ED: BL WORD FIND IF
   2+ DUP ['] BRANCH SWAP ! \ write BRANCH opcode
   2+ HERE SWAP !		   \ write branch address
   ]					    \ enter compile mode
 ELSE
   TRUE ABORT" not found"
 THEN ;

: ;ED
   $832C ,	  \ compile EXIT opcode
   [COMPILE] [  \ enter interpret mode
; IMMEDIATE

 

Un-tested as I don't have my laptop with me. I'll update the site tonight. I'm off to the dentist this afternoon so I'll be at home drooling like a baby come 4pm :_( so I'll fire up Dreamweaver and my FTP software!

Link to comment
Share on other sites

Can I add to this thread...

 

What are the implications for TF1.2 as regards F18A support. Like a few of us i am lucky to have an F18 installed and now have a loverly rock steady VGA display but with a bad keyboard (another story)

 

Mr Willsy, are you planning to add support for F18 or just additional addons for TF1.2?

Link to comment
Share on other sites

Just had a thought regarding ED: and ;ED.

 

I'm not sure which build of TF V1.2 you're running, but you might find that it doesn't work if you are using the (I think) the last two builds of V1.2. The reason is because BRANCH and 0BRANCH were changed to take an explicit address, rather than an offset (makes it slightly faster). The code published uses an offset. I'll change the code to produce an explicit address (ED: will get simpler, less code!).

 

Mark

 

Ahhh, what is ED??? Willsy, I'm still a total nube at this, remember?

I'm still using version 1.1 because I'm testing TF on my real console.

Link to comment
Share on other sites

Ahhh, what is ED??? Willsy, I'm still a total nube at this, remember?

I'm still using version 1.1 because I'm testing TF on my real console.

 

I'll give you a preview because Mark is sawing logs at the moment! Then, he can clean up my attempt at an explanation. ED: and ;ED are part of a quick and dirty solution to the one-more-bug syndrome---you know---where you code a word that fails, but you're sure you know what the problem is, so you fix it only to have it fail again. But, you know what's wrong this time and you keep up these stutter steps into the wee hours. One of the problems with re-programming a word is that it might be way back in your definitions, so every time you FORGET the word to rewrite it, you have to reload all the words behind it! ED: and ;ED allow you to rewrite the word on the command line without affecting any other words until you get it right. All you need to do is to treat ED: like : and ;ED like ;.

 

Say, for example, you wrote this:

 

: TESTLOOP 10 0 DO LOOP ;

 

The problem is that you intended to display the loop index, but your bigger problem is that TESTLOOP is ten words back in the dictionary and you'd like to fix it without reloading the other ten words. Enter ED: and ;ED:

 

ED: TESTLOOP 10 0 DO . LOOP ;ED
<----Uh-oh! Still wrong! Underflow...

 

ED: TESTLOOP 10 0 DO I . LOOP ;ED
<----Ah! Now it should work!

 

You can repeat this procedure pretty much as long as you want. You do have to completely redefine the word. It's not truly an edit. It also chews up dictionary real estate, so you eventually need to actually FORGET the word and make a clean redefinition if you want to keep it; but, it can save you some debug time along the way.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Well I did additional sprite testing after reading your comments (thanks :) ), and the code below just refused to work in TF1.1, and I suspected it was the joystick patch at the root of the problem. So I removed the patch and entered the same program in Classic 99 using TF1.2 and it worked perfectly.

 

: INIT 1 GMODE 12 SCREEN ;	
: DEFCHR1 DATA 4 $18BD $FFBD $3CBD $FFBD 384 DCHAR ;		
: DEFCHR2 DATA 4 $EE44 $FEFF $FFFE $44EE 385 DCHAR ;		
: DEFCHR3 DATA 4 $BDFF $BD3C $BDFF $BD18 386 DCHAR ;		
: DEFCHR4 DATA 4 $7722 $7FFF $FF7F $2277 387 DCHAR ;		
: DEFSPR 0 80 125 384 15 SPRITE 0 -2 0 SMLIST ;				
: READJOY 0 JOYST			
CASE						
16 OF 0 -2 0 SMLIST ENDOF
2 OF 0 0 -2 SMLIST ENDOF
4 OF 0 0 2 SMLIST ENDOF
8 OF 0 2 0 SMLIST ENDOF
ENDCASE ;					
: START INIT DEFCHR1 DEFCHR2 DEFCHR3 DEFCHR4 DEFSPR			
BEGIN READJOY 0 1 SPRMOV BREAK? AGAIN ;				

 

It was blazing fast!

 

Any other major issues I need to know about regarding TF1.1 so I don't try to pull my hair out every night? :roll:

Edited by Vorticon
Link to comment
Share on other sites

I'll give you a preview because Mark is sawing logs at the moment! Then, he can clean up my attempt at an explanation. ED: and ;ED are part of a quick and dirty solution to the one-more-bug syndrome---you know---where you code a word that fails, but you're sure you know what the problem is, so you fix it only to have it fail again. But, you know what's wrong this time and you keep up these stutter steps into the wee hours. One of the problems with re-programming a word is that it might be way back in your definitions, so every time you FORGET the word to rewrite it, you have to reload all the words behind it! ED: and ;ED allow you to rewrite the word on the command line without affecting any other words until you get it right. All you need to do is to treat ED: like : and ;ED like ;.

 

Say, for example, you wrote this:

 

: TESTLOOP 10 0 DO LOOP ;

 

The problem is that you intended to display the loop index, but your bigger problem is that TESTLOOP is ten words back in the dictionary and you'd like to fix it without reloading the other ten words. Enter ED: and ;ED:

 

ED: TESTLOOP 10 0 DO . LOOP ;ED
.

 

You can repeat this procedure pretty much as long as you want. You do have to completely redefine the word. It's not truly an edit. It also chews up dictionary real estate, so you eventually need to actually FORGET the word and make a clean redefinition if you want to keep it; but, it can save you some debug time along the way.

 

...lee

Nice. I definitely could use this little tool. Thanks for the explanation :)

Link to comment
Share on other sites

Well I did additional sprite testing after reading your comments (thanks :) ), and the code below just refused to work in TF1.1, and I suspected it was the joystick patch at the root of the problem. So I removed the patch and entered the same program in Classic 99 using TF1.2 and it worked perfectly.

 

: INIT 1 GMODE 12 SCREEN ;	
: DEFCHR1 DATA 4 $18BD $FFBD $3CBD $FFBD 384 DCHAR ;		
: DEFCHR2 DATA 4 $EE44 $FEFF $FFFE $44EE 385 DCHAR ;		
: DEFCHR3 DATA 4 $BDFF $BD3C $BDFF $BD18 386 DCHAR ;		
: DEFCHR4 DATA 4 $7722 $7FFF $FF7F $2277 387 DCHAR ;		
: DEFSPR 0 80 125 384 15 SPRITE 0 -2 0 SMLIST ;				
: READJOY 0 JOYST			
CASE						
16 OF 0 -2 0 SMLIST ENDOF
2 OF 0 0 -2 SMLIST ENDOF
4 OF 0 0 2 SMLIST ENDOF
8 OF 0 2 0 SMLIST ENDOF
ENDCASE ;					
: START INIT DEFCHR1 DEFCHR2 DEFCHR3 DEFCHR4 DEFSPR			
BEGIN READJOY 0 1 SPRMOV BREAK? AGAIN ;				

 

It was blazing fast!

 

Any other major issues I need to know about regarding TF1.1 so I don't try to pull my hair out every night? :roll:

 

Ha ha!! Nice one! You're on your way! :thumbsup: :thumbsup:

 

Well done!

 

Er, yeah, sorry about that - I think that patch for Joyst is also bugged. Er, I'll have to patch the patch!

 

Regarding your code, I would factor it slightly differently, but that's not important right now.

 

Just for kicks, try it again in V1.2 without the BREAK? in the word START.

 

See how much a keyboard scan slows down the program? Bloody shocking, isn't it?? :-o

 

You could use the joystick fire button to exit, by adding an extra case in READJOY:

 

1 OF TRUE ABORT" Program exit" ENDOF

 

That would be faster than keyboard scan.

 

Also, it's probably faster (never tried it) to use SPRLOC to mve a single sprite around.

 

In fact that would make a very good excercise for you: Use a variable for X and another for Y and move the sprite around using the variables.

 

Tips: Use the language reference on the website, and look at VARIABLE, @, !, 1+ 1-, etc.

 

Also look at the variables tutorial here for more information.

 

Finally, you may prefer to use VALUES rather than variables (I do). There's a tutorial on VALUES on the website, too!

 

You have 24 hours to deliver your homework! :grin:

 

Regarding Lee's comments on ED - much better explanation than me, Lee! Thanks! :thumbsup:

Link to comment
Share on other sites

Willsy, how would you factor this differently?

 

Like this:

 

: UDGs
 DATA 4 $18BD $FFBD $3CBD $FFBD 384 DCHAR
 DATA 4 $EE44 $FEFF $FFFE $44EE 385 DCHAR
 DATA 4 $BDFF $BD3C $BDFF $BD18 386 DCHAR
 DATA 4 $7722 $7FFF $FF7F $2277 387 DCHAR ;

: DEFSPR
 0 80 125 384 15 SPRITE   0 -2 0 SMLIST ;

: INIT
 1 GMODE  12 SCREEN  UDGs  DEFSPR ;

: READJOY
 0 JOYST
 CASE
   16 OF 0 -2 0 SMLIST ENDOF
   2 OF 0 0 -2 SMLIST ENDOF
   4 OF 0 0 2 SMLIST ENDOF
   8 OF 0 2 0 SMLIST ENDOF
 ENDCASE ;

: START
 INIT
 BEGIN
   READJOY  0 1 SPRMOV  BREAK?
 AGAIN ;

 

But really, it's no big deal. And factoring is a matter of personal taste and style. It's just that, in the case of this particular program, (in my opinon) the definition of the graphics was 'associated' (in my mind) with initialisation, so I had INIT call the code to define the graphics, rather than have it done in START.

 

Also, I put all the UDGs in one word, saving dictionary space.

 

Also, have a look at DEFSPR and INIT. You may notice that I've seperated logically different parts of the definition with two spaces. This is the equivalent of a paragraph in written English - I.e. in English, when we change the subject, we start a new paragraph. In Forth we do the same, but we leave two or three spaces as a paragraph marker. This makes it much easier to read the code later. For example:

 

0 80 125 384 15 SPRITE    0 -2 0 SMLIST

 

See the extra spaces after SPRITE? So, when reading it back later, we can clearly see the end of the sprite definition code, and the beginning of the initialisation of the sprite movement list.

 

You'll see this advocated in various Forth books (Brodie et al) and I think it's a good habit to get into as early as possible. It will make your code much more readable.

Link to comment
Share on other sites

Good stuff. For starters, just try a program to move a single sprite around the screen using variables.

 

Then, when you have done that, do the same using NO variables at all! (It can be done - but it really hurts the non-Forth brain! - It's a very good excercise though).

 

Final tip: I don't know why, but when I'm figuring out difficult code, I always revert to pen/pencil and a notebook. Never the screen and keyboard. Just thought I'd throw that in :-D

Link to comment
Share on other sites

Out of curiosity, how does TI Forth compare to TF speed wise?

 

It varies. TF is generally faster than TIF, but I've written stuff where TIF was actually faster. With code that includes the display in a loop, TIF definitely loses. @Willsy's display routine is much faster than TIF's.

 

...lee

Link to comment
Share on other sites

Lee, it seems there is something funny going on with the -TRACE option in TIF.

When I try to load it, I get the following:

 

-TRACE : isn't unique. ok

 

I also get a couple of numbers on the stack, namely 0 and 5.

 

Subsequently, I get no errors when I execute the word TRACE, but again I get a couple of numbers placed on the stack.

 

I came across this while testing the recursion example on page 29 of your TIF manual which incidentally is missing an IF in the colon definition as it should be

: FACT DUP 1 > IF DUP 1 - MYSELF * ENDIF ;

 

Tracing the execution of the above using TRON gives me correct stack results except for 2 additional unchanging digits at the bottom of the stack.

 

Am my missing something or is there a problem with TRACE?

 

Walid

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