Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Community Reputation

1,488 Excellent

About TheBF

  • Rank

Profile Information

  • Gender
  • Location
    The Great White North
  • Interests
    Music/music production, The Forth programming language and implementations.
  • Currently Playing
  • Playing Next
    Trumpet ;)

Recent Profile Visitors

5,727 profile views
  1. I pulled one SWAP out of COINC which speeds it up a little bit : COINC ( spr#1 spr#2 tol -- ?) >R SP.Y [email protected] SPLIT \ expand POSITION for speed ROT SP.Y [email protected] SPLIT ( -- col row col row) ROT - ABS [email protected] < -ROT - ABS R> < AND ; I put together a little test to see how it performs with automotion. The test is not using COINCXY for testing the borders of the screen. I find it easier to read the sprite descriptor table (SDT) X and Y coordinates separately. I have CODE words called SP.X SP.Y to compute the VDP addresses given a sprite# parameter. For clarity there is also [email protected] and [email protected] . This would not be a big deal in a language with local variables but needlessly reading two values onto the stack when you don't need both just means you have to do more shuffling. I am beginning to think the SPRITE command set from BASIC is not optimal for Forth for this reason. Here is the new code and a test video. It seems to work and takes a lot less space than the old one. NEWCOINCTEST.mp4
  2. The Dreaded Sprite Coincidence While looking to update a PONG demonstration game I started to wonder about coincidence detection. My original code was an optimized version of the TI-Forth code. I wrote some CODE words and the net result was I got COINC to be 2X faster but it always seem needlessly complicated to me. My Sprite COINC using distance calculation That's a lot of code to compare two X,Y pairs! I found this great site here https://ti99resources.wordpress.com/documents/ and took a look at an Assembly Language book. I was curious how an Assembly Language coder would do this. Subtraction of course and comparison to a value. DUH! I have words that index into the sprite table and I have a word to read 2 VDP bytes at once. ( [email protected]) I have a code word that splits an integer into 2 bytes. Putting that all together in Forth gave me this and even without optimization it is still faster than my master work above based on the TI Forth code. Summing the squares was indeed overkill. : COINC ( spr#1 spr#2 tol -- ?) >R SP.Y [email protected] SWAP SP.Y [email protected] ( <COL,ROW> <COL,ROW>) SPLIT ROT SPLIT ( -- col row col row ) ROT - ABS [email protected] < -ROT - ABS R> < AND ;
  3. Final inline optimizer handles USER variables but not completely. I wimped out and simply compile the address for the current workspace. It's mostly for amusement because if you really need a lot of speed Forth Assembler is best for the 9900. Spoilers show the final code that will be released. The error message for an un-optimizable word has been improved and the offending word will be printed by ?ERR. The two little videos show Camel99 Forth V2.62C and TurboForth running the same code to calculate 10,000 primes. They both come in at about 6.3 seconds on my stop watch. The TI-99 elapsed timer is a little high. You can also see the code running called OPTIMUSPRIMES which is running with all the primitives inlined. It runs in about 4.1 seconds. CAMEL99_PRIMES.mp4 TURBOFORTH_PRIMES.mp4
  4. Thanks. I still have to add a code fragment to handle USER variables but now the framework makes it straightforward. Yes I had a similar problem with the primitives in scratchpad RAM. They defied my detection method for code words. This is why I created duplicates of the problem words. All of this is pointing in the direction of moving to building a native code Forth kernel for TI-99. I spoke with Stephen Pelc the CEO of MPE Forth a few years back and he told me that when they switched to their VFX native code compiler development they were benchmarking the new compiler against their older threaded versions. He said "We stopped comparing when the difference was 12X faster". I have been sidetracked in that endeavour because I wanted to have a complete threaded system that I was good before moving on. It's getting close.
  5. Just to see what it would take I continued working on my INLINE[] optimizer. I realized that I should have emulated the Forth compiler loop to make it easier. With that awakening I added the ability to compile literal numbers inline. Next I made use of the fact that every Forth word has an kind of identifier as the first cell of its definition. This can be treated like a 'type' identifier as you would see in typed languages. Armed with that knowledge I could determine if a word was a VARIABLE or a CONSTANT and compile the appropriate code for those words as well. The got a little more complicate but it makes sense to me. It reduced the running time of the 10,000 number Sieve benchmark by 10% just by inlining one constant in the inner loop. Not bad.
  6. This is a cool idea. I need to try this in Forth.
  7. Pulled another classic off a diskette recently. MELTDOWN by Steve Langguth From Home Computer Magazine It's weird to think about how long ago it was AND that I typed this listing from a book.
  8. Who am I kidding. Once I opened that code up I couldn't just leave it alone. I found a bunch of stupid stuff in OREGON Trail that I fixed in the new version post in previous post. You can read the source code if you really want to know the details. Better yet change it up and give it back to us. I also added some problems with clothing wearing out so invest your budget wisely. Suffice to say you now can't win by always pressing CONTINUE like you could before. That will be it for Oregon trail for a while ... I hope. Maybe I should do a Yukon Goldrush and have a few polar bears and grizzlies in the mix...
  9. I couldn't sleep so I thought I would finalize something I started a long while back. Having never written an adventure game I thought it would be fun to re-work Oregon Trail by Majestyx and try and create a game language in Forth. It turned out the game language made adding game features and decisions so easy that I kept adding things to it. It's now over 1000 lines. Some of the game language features are: ." is re-written so it compiles strings to VDP RAM to save CPU RAM for program logic. PRINT." is the same as ." but adds the new-line first like BASIC Print. IF etc. has been replaced by: DOTHIS <CODE> OTHERWISE <CODE> ENDTHIS ... prints a small random number of dots at 1/4 second intervals to make it look like time is passing %CHANCE lets you alter the game chances of things happening. Used with DOTHIS Vector tables provide a way to run random blocks of code to select random diseases, animals and body-parts. Enhancements: It could be further enhanced to make the scripting even simpler I suppose, but I didn't feel the need to go further. The game itself needs tweaking to make it more challenging. Another natural enhancement would be to replace the menus with game commands that are interpreted by Forth. I started the process of making the calendar accurate for the actual year of the game, but lost interest. To Run: Unzip OREGON.ZIP onto a TI99 DISK. Start CAMEL99 V2.62 from DSK1. with E/A 5 menu wait for the start file to complete Type : INCLUDE DSK?.OREGON Wait for it to compile. It will auto start *NEW* Source code for V1.5 the curious OREGON.zip
  10. Revisiting INLINE[] (A Poor Man's JIT) A few years back I explored stealing code fragments from the Forth kernel and compiling them inline. The idea is that each Forth primitive has a three instruction overhead called the "inner-interpreter". If we remove those three instructions between each primitive code routine things run much faster; as much as 2X faster. The ideal is to be able to just put an inline command in a normal definition and compile the machine code for the primitives inline. Inlining machine code is a great strategy in a sub-routine threaded system or even a direct threaded system but in the classical indirect threaded system the overhead is rather large, so much so, that I found if I wanted to use INLINE[] it made more sense to make a new CODE word like this: CODE DUP>R INLINE[ DUP >R ] NEXT, ENDCODE Then I would use this new word as a replacement for the words DUP >R where ever the phrase appeared in the code. This save space by calling DUP>R everywhere in the code so it's not all bad but I wanted the freedom to eliminate that extra step. It occurred to me that with empty memory in LOW-RAM at >2000, I could compile the new word as a "header-less" CODE word in low-RAM and then compile the address of that word directly into my Forth definitions. It's a temporary piece of code that is built at compile time and the address of the code is compiled into a new definition. It's sort of a poor mans JIT (just in time compiler) I was surprised to see that with a few HEAP support words it didn't take too much to add it to the code I already had. INLINE2.FTH To see what difference it makes, here is the Sieve of Erathosenes which normally runs in 7.8 seconds in Camel99 Forth V2.6 With a few key phrases of code primitives put inline the time got down to 4.65 seconds. An improvement of 40%. The code in this example used 168 bytes of the HEAP to hold the machine code routines. Limitations (Some primitives like ">" don't work because of the way they were coded in the kernel. Tricks were used to save space, so don't include them inline. You cannot INLINE[ ] a high level Forth word. Only CODE words (primitives) work with this simple system. Improvements An actual JIT could be made by modifying the Forth compiler loop to look for patterns of CODE primitives and compiling them inline automatically. Something to think about for the future. Sieve program with INLINE[ ] code.
  11. I believe we would say he is good at "debugging" Bugging is a synonym for programming because PROGRAMMING is how we put the "bugs" IN the programs.
  12. LOL. You mentioned you wanted a way to convert PC text files to DV80 source fiels. This was my simple solution but you wanted something for entire directories and I bet you would want full REGEX selecting as well. (I would)
  13. I did have a word to do that but removed it. Unless I go to code words the speed difference is not that great between [email protected] C! and [email protected] VC!. The Forth overhead swamps the difference on short strings. I should to go there in ED99 to select (hilight) an entire file however. I think I will do some experiments on a 4K buffer in ALC.
  14. I finally got around to formalizing support for an inverted font in Camel99 Forth. A nice out-growth of the effort was the creation of VCMOVE which allows VDP to VDP movement using a dynamic buffer in low RAM. This makes copying a font from the default position to a new position in VDP RAM very easy although it does use a lot of return stack juggling. With your font in VDP RAM you must first run INVERTFONT which copies the font to >80+ASCII value and then inverts all the bits in VDP RAM for the copied patterns. You can then use HITYPE to type an inverse colored stack string (addr,len), or HILITE an area of the screen or NORMAL an area of the screen. Edit: ANS Forth has the word INVERT which is faster than -1 XOR. DUH!
  15. Beery motivated me to try something that I was wanting to make anyway. In the past I have been using the TI editor as simple way to convert a PC text file to DV80. It's not great but it works. I realized that I had a pretty good set of utilities in my SHELL program so I tried adding something called WAITFOR that accepts text from the keyboard and saves it to a file when you press BREAK (FCTN 4). The videos show it working and how you use the COPY command to take TI files back to the windows clipboard. All of this is made easy because of Classic99. Shell utility code with WAITFOR added at the end WAITFOR_FILE.mp4 COPY_TO_CLIP.mp4
  • Create New...