Jump to content
IGNORED

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


Lee Stewart

Recommended Posts

A note on joystick use—

 

There is no need to worry about JMODE if you are not using JOYST for joystick action. It has no effect on normal keyboard use. It only affects which word, JKBD or JCRU , JOYST invokes when it is executed. The reason I set things up this way is to remain compatible with TI Forth while also allowing monitoring joystick action through the CRU if that was the programmer's desire. You are using JCRU directly, so setting JMODE is superfluous.

 

...lee

Link to comment
Share on other sites

There are a couple of problems I see with game play. With the first crash, the game is over because the sprites are still overlapping when the game continues. All the lives are gone before the colliding cars are free of each other. Resetting the cars to initial positions after each crash would mitigate this. If you don't want to reset to the initial positions, you will need to add at least the length of a car to all the car positions because you don't really know which car hit you. Actually, you could figure it out by stopping motion after a crash, reading the position of each car with SPRGET or COINC , moving the colliding enemy car beyond you and only then restarting motion.

 

...lee

Link to comment
Share on other sites

Sprite patterns should not have anything to do with collision unless they are associated with a sprite. The only reason I can contrive for the behavior you see is not using a lower-numbered sprite. Anytime you define a sprite in fbForth, all lower-numbered sprites are checked for whether they have been marked as undefined with their y coordinates set to >D0. If that is the case their y coordinates are set to >C0 (192). The effect of this immediately after invoking GRAPHICS and DELALL , is that all previously undefined sprites will be defined as though by

 

0 192 0 0 0 SPRITE

Their motion vectors will also each be 0. With the magnification factor set to 2, character patterns 0 3 are, indeed, associated with each of those previously undefined sprites. I checked the collision bit with overlapping, off-screen sprites and it was not set, contrary to the E/A Manual, so I am puzzled. It certainly could be a bug in fbForth. If we find any such bugs, they will not survive! :grin:

 

...lee

 

So could this have been caused by my starting with sprite number 1, instead of 0. ? I started this project by coding some XB, and then I'm porting that to practice forth. I'll run that experiment when I get home.

 

 

Your code has no doubt changed, so I won't get too much into it, yet. Just a couple of comments. The conventional way to show stack effects in Forth is to separate stack entries with spaces, which would change

 

: .AT ( X,Y -- ) SWAP 32 * + CURPOS ! ;

to

 

: .AT ( X Y -- ) SWAP 32 * + CURPOS ! ;

Also, with Y on the top of the stack (rightmost item), your code should be

 

: .AT ( X Y -- ) 32 * + CURPOS ! ;

But, there is already a resident word with a more generalized form of this definition. It is actually written in ALC; but, here is the equivalent high-level Forth:

 

: GOTOXY ( X Y -- ) SCRN_WIDTH @ * + SCRN_START @ + CURPOS ! ;

Of course, it could be that your stack effects are backwards, in which case

 

: .AT ( Y X -- ) SWAP 32 * + CURPOS ! ;

could be written

 

: .AT ( Y X -- ) SWAP GOTOXY ;

...lee

 

I love the feedback. Is it acceptable to follow a pattern of no stack effects if there should be none?

And thanks for the pointer to GOTOXY, my implementation of .AT was going to get me in trouble, and wasn't working right anyway :)

 

 

Perhaps you know this: You can load successive blocks with --> as the last word on each block except, of course, the final block. That way, the blocks can start anywhere without needing to redefine a word like LOADALL .

 

...lee

I did not know this. I was wondering how horrible it was for me to do what I was doing loading several blocks... What are some best practices in this area? Multiple block management seems like it will get complicated soon.

 

 

A note on joystick use

 

There is no need to worry about JMODE if you are not using JOYST for joystick action. It has no effect on normal keyboard use. It only affects which word, JKBD or JCRU , JOYST invokes when it is executed. The reason I set things up this way is to remain compatible with TI Forth while also allowing monitoring joystick action through the CRU if that was the programmer's desire. You are using JCRU directly, so setting JMODE is superfluous.

 

...lee

I like to initialize properly as much as I can, and intended to migrate to JOYST so keyboard support would be for free, but I started with JCRU cause I was being lazy first. :)

 

There are a couple of problems I see with game play. With the first crash, the game is over because the sprites are still overlapping when the game continues. All the lives are gone before the colliding cars are free of each other. Resetting the cars to initial positions after each crash would mitigate this. If you don't want to reset to the initial positions, you will need to add at least the length of a car to all the car positions because you don't really know which car hit you. Actually, you could figure it out by stopping motion after a crash, reading the position of each car with SPRGET or COINC , moving the colliding enemy car beyond you and only then restarting motion.

 

...lee

Gameplay is horrible :) In the XB version I wrote in '84 after a crash, it just resets, and keeps looping... no scoring or anything game-ish. So I was trying to port that first, before making it better. Hopefully I'll make it a lot better. I have actually updated it to reset to initial positions, cause that is what my childhood version did :)

 

All the help is massively appreciated, and I love the feedback. Thanks so much!

 

-M@

Link to comment
Share on other sites

So could this have been caused by my starting with sprite number 1, instead of 0. ?

 

Yes, if you did not start with DELALL after GRAPHICS . This is because GRAPHICS only zeros the Sprite Attribute List. This effectively creates all 32 sprites using the pattern for chr #0 (default font has that pattern with all pixels on), transparent color and positioned at 0,0 (upper left corner). So, all the sprites you did not define were invisible and sitting right under the first enemy sprite with no chance for your program!

 

DELALL does some checking for proper VDP modes (throws an error if in a text mode), clears the motion table if not in bitmap mode and undefines all sprites by placing >D0 in the y location of every sprite.

 

I started this project by coding some XB, and then I'm porting that to practice forth. I'll run that experiment when I get home.

 

Good idea. You've just discovered that Forth is similar to Assembler when it comes to tables and lists, viz., they are zero-based. One exception is the first block of a blocks file, which starts at 1 because it was easier when I converted TI Forth to a file basis for blocks.

 

I love the feedback.

 

I enjoy giving feedback when I can actually dig out the answers.

 

Is it acceptable to follow a pattern of no stack effects if there should be none?

 

If I understand you, showing stack effects is certainly not required; but, it certainly makes it easier on yourself and later programmers to include them and, yes, even if there are no stack effects, it helps to know that. I have spent countless hours dis-Forthing words to try to figure out what they were doing. Many did not include the stack effects, which often made the task a good bit more difficult.

 

I did not know this. I was wondering how horrible it was for me to do what I was doing loading several blocks... What are some best practices in this area? Multiple block management seems like it will get complicated soon.

 

It is not horrible at all. I just wanted to point out the convenience of an existing word. TurboForth has a word similar to yours that you can easily use in fbForth. Its definition is

 

: THRU ( start-block end-block -- ) 1+ SWAP DO I LOAD LOOP ;

CLOAD (conditional load) is a good word to keep in mind. CLOAD allows you to avoid loading requested blocks or prerequisite blocks if they have already been loaded. Check the manual for more.

I like to initialize properly as much as I can, and intended to migrate to JOYST so keyboard support would be for free, but I started with JCRU cause I was being lazy first. :)

 

Well, you can always give the user a choice at the beginning of the game. JKBD (or JOYST with JMODE = 0) certainly allows both standard keyboard and joystick responses, but it cannot handle direction and fire at the same time. JCRU (or JOYST with JMODE ≠ 0) can and is faster. Of course, the program must deal with different values; but, you're already doing that.

All the help is massively appreciated, and I love the feedback. Thanks so much!

 

-M@

 

You are most welcome! :)

 

...lee

Link to comment
Share on other sites

It is not horrible at all. I just wanted to point out the convenience of an existing word. TurboForth has a word similar to yours that you can easily use in fbForth. Its definition is

 

: THRU ( start-block end-block -- ) 1+ SWAP DO I LOAD LOOP ;

CLOAD (conditional load) is a good word to keep in mind. CLOAD allows you to avoid loading requested blocks or prerequisite blocks if they have already been loaded. Check the manual for more.

 

...lee

 

The next block word turns out to be very nice. With my LOADALL, or THRU, a typical code-test cycle would have me FORGET my first word in block 1, and then perform a 1 LOAD, which would call LOADALL. If I wanted to go faster, but was changing something on block 5, I'd FORGET the first word on that block, and then 5 LOAD 6 LOAD... But by using '-->' at the end of each block that continues on to the next, I can FORGET and then load the lowest block that was edited, and the rest follow. Very cool.

 

-M@

Link to comment
Share on other sites

While working on the above sprite explanations, I discovered a bug in the code for SPRPUT , which is also used by SPRITE . The bug causes the x coordinate of a sprite to be decremented if the y coordinate input is 0! I will fix it in the imminent release of fbForth 2.0:3

 

...lee

Link to comment
Share on other sites

While working on the above sprite explanations, I discovered a bug in the code for SPRPUT which is also used by SPRITE . The bug causes the x coordinate of a sprite to be decremented if the y coordinate input is 0! I will fix it in the imminent release of fbForth 2.0:3

 

...lee

Maybe this is related? When I use decimal negative number for x motion vector, the sprite moves up the screen.

-4 0 0 MOTION

where I only expect my sprite to move to the left? But the following moves to the left just fine.

252 0 0 MOTION
Link to comment
Share on other sites

 

Maybe this is related? When I use decimal negative number for x motion vector, the sprite moves up the screen.

-4 0 0 MOTION

where I only expect my sprite to move to the left? But the following moves to the left just fine.

252 0 0 MOTION

 

'Tis, indeed, the same buggy code, but in a different place. :woozy: To clarify, as I see the code, the sprite with the first motion vectors should move in the same direction as one set with

 

252 255 0 MOTION

 

that is, it should move in a west-by-northwest direction (1 up for every 4 left). Is that the case?

 

...lee

  • Like 1
Link to comment
Share on other sites

'Tis, indeed, the same buggy code, but in a different place. :woozy: To clarify, as I see the code, the sprite with the first motion vectors should move in the same direction as one set with

 

252 255 0 MOTION

that is, it should move in a west-by-northwest direction (1 up for every 4 left). Is that the case?

 

...lee

 

Yep, that is the case. 1 up for every 4 left.

 

Does forth have a signed-int16 to signed-byte conversion word? It seems that you are trying to take care of that in words that expect signed bytes, but numbers on the stack are always treated as int16. The JOYST routine through me for a loop too... The output vectors are signed bytes ( -4 is represented as 252 ) so it quite naturally fed the inputs of the MOTION word, until I tried to multiply the value. You could probably teach us about some conversion words that would be handy in these situations.

 

-M@

Link to comment
Share on other sites

Yep, that is the case. 1 up for every 4 left.

 

Does forth have a signed-int16 to signed-byte conversion word? It seems that you are trying to take care of that in words that expect signed bytes, but numbers on the stack are always treated as int16. The JOYST routine through me for a loop too... The output vectors are signed bytes ( -4 is represented as 252 ) so it quite naturally fed the inputs of the MOTION word, until I tried to multiply the value. You could probably teach us about some conversion words that would be handy in these situations.

 

-M@

 

The problem with my code for SPRPUT and MOTION was purely an ALC problem. I made a wrong assumption and it cost me. It is fixed in the next build, which will be ready in time for the Faire. Anyone with a cartridge can burn the new image themselves or I can trade EPROMs.

 

I puzzled long and hard over what to do with the joystick values that the console KSCAN routine returns. I knew that both BASICs returned -4 instead of 252 (FCh); but, in the end, it was compatibility with TI Forth that won out. There are no fbForth words that deal explicitly with conversion of 8-bit numbers to/from 16-bit numbers; but, it would not be difficult to write them. The easiest way to convert with existing words is by using SLA , SRA and AND .

 

To convert an 8-bit number on the stack to a 16-bit to preserve the 8-bit sign, simply issue the following commands with the relevant 8-bit number on the stack:

 

8 SLA 8 SRA

 

After any manipulations, the number can be converted back to 8-bits by truncating the leftmost 8 bits with

 

HEX 00FF AND <----corrected!!

 

Actually, you don't even need to do that if the number is going to be stored somewhere as a byte with C! . That will strip the leftmost 8 bits in the process.

 

There are probably other ways to do this I haven't yet thought of. At any rate, if you define words to do these operations, you should eventually re-define them in Forth Assembler for speed.

 

...lee

 

[Edits are the same color as this line.]

Edited by Lee Stewart
Link to comment
Share on other sites

I'll be bringing my FbForth cart to trade the Eprom at the Faire :) BTW Willsy, will you be making arrangements for someone to burn Eproms for TF 1.2.2 at the Faire as well?

 

I think Bob Carmany is going so I'm sure he'll step in to do some EPROM burning. If not, maybe Lee can do it.

Link to comment
Share on other sites

OK—So far,

  • I have fixed the following bugs:
    • BSAVE was not explicitly saving the pointer to the last word in each of the FORTH and ASSEMBLER vocabularies.
    • SSDT was improperly setting the address of the Sprite Pattern Descriptor Table.
    • SPRPUT was setting the x position to 255 (rightmost position) if y was 0.
    • MOTION was setting the x|y vector to -1 if the y|x vector was negative.
    • If sprite automotion was not stopped in Graphics mode, blinking text appeared in Text, Text80, Bitmap and Split modes.
  • I have added the following words to the resident dictionary:
    • ASCII—pushes to the stack the ASCII code of the following character in the input stream
    • ELSEOF—catchall (default) OF for CASE ... ENDCASE construct
    • ALIGN—aligns HERE to an even address boundary
    • RP@—returns the address of the top of the return stack
    • TOKEN—general-purpose string tokenizer
    • S"—state-smart string tokenizer with " as delimiter
    • PAGE—clears screen and puts cursor at 0,0

I am trying to jockey ROM space around to fit VLIST into the resident dictionary before I release fbForth 2.0:3. I should be able to figure out whether or not I can do that in the next day or two.

 

Woohoo! :-o I managed to get VLIST into the cartridge. See post #1 of this thread for downloads.

 

...lee

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

Wow! I finally managed to find the room for VLIST, but ran into another problem that's been just waiting to happen again—too many labels for Asm994a! Asm994a was telling me I had 6 duplicate labels, which I knew was not true. The number of labels was up to 2872 (at least, that is the line count of labels at the end of the listing). I started looking for at least 6 extraneous labels, which are now in short supply from the last time I cleaned them up. I managed to find at least 7.

 

Everything seems to be working, now. I just need to thoroughly test all of the new words before I commit this all to post #1 and EPROMs.

 

Current free ROM:

 

Bank Bytes

---- -----

0 16

1 44

2 54

3 30

 

...lee

  • Like 1
Link to comment
Share on other sites

I'm still hoping to find time in January to get into this, but by that time the book I had printed off will probably be obsolete, possibly even my cartridge too if anything cool is written for it with all these changes.

 

There are workarounds for all of the bugs and the new words can be defined before loading other words that use them.

 

...lee

Link to comment
Share on other sites

Squashed two more bugs :spidey: :-o :

  • DELALL was only marking the first 8 sprites as deleted, i.e., y = D0h, when it should have been doing it for all 32! The upshot of this bug is that, as soon as you define sprite #7, all of the remaining sprites are suddenly defined as char 0, transparent and positioned at 0,0!
  • Automotion was not stopped when changing VDP modes. For some reason, which I would likely need to pore over the code for the console’s KSCAN routine to understand, if sprite automotion is enabled and sprites were left defined, TEXT80, Bitmap and SPLIT modes show blinking areas on the screen that correspond to those sprites, particularly those defined with patterns in the text PDT area.

I tried to get more testing before I released the cartridge a year ago, but could only get a handful of folks to help. It was @jedimatt42’s recent forays into fbForth 2.0 that teased out these last bug fixes. Thanks, Matt!

 

...lee

Link to comment
Share on other sites

Sweet! That ties the explanations about sprites and COINCALL back to reality for me. :) Thanks again for the help... I was able to work around each of those issues, and get the first basic game I ever wrote, ported to fbForth. That was a great exercise for me. Now I can learn some tricks like multi-layered sprites, and many others, to make it into the game I want it to be. ( The American Grand Prix is tomorrow, hopefully that will be inspiring - if the rain stops )


I believe I saw automotion appear to mutate character definitions after switching to TEXT ( 40 column ) mode as well. I didn't think of this as a bug at the time, as it is so easy to do something like create a word say, 'DEVMODE' that stops motion and sets the text mode I want... And I couldn't particularly tell how much initialization the mode commands intend to be responsible for.


As for Ω's concern about an obsoleted printed manual, it would be great to get the added resident words in as an Addendum PDF. I like my reference material in physical form too, mostly so I can step away from the desk when I'm studying. https://goo.gl/photos/56AM8opJVGbGBbHX9 <-- There is a picture of my fbForth spiral bound book.


-M@
  • Like 1
Link to comment
Share on other sites

 

I tried to get more testing before I released the cartridge a year ago, but could only get a handful of folks to help. It was @jedimatt42’s recent forays into fbForth 2.0 that teased out these last bug fixes. Thanks, Matt!

 

...lee

 

Frankly, the only way to fully test a language is by creating a complete project with it. Not only are obscure bugs frequently teased out, but it's also an opportunity to add enhancements as well. The great thing about you and Willsy is that you are incredibly responsive and available, so fixes are done very quickly, sometimes within hours! Thank you guys :)

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