Jump to content

Search the Community

Showing results for tags 'Forth'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • Atari Systems
    • Atari General
    • Atari 2600
    • Atari 5200
    • Atari 7800
    • Atari Lynx
    • Atari Jaguar
    • Atari VCS
    • Dedicated Systems
    • Atari 8-Bit Computers
    • Atari ST/TT/Falcon Computers
  • Classic Consoles
  • Classic Computing
  • Modern Consoles
  • Gaming General
  • Marketplace
  • Community
  • Community
  • Game Programming
  • Site
  • PC Gaming
  • The Club of Clubs's Discussion
  • I Hate Sauron's Topics
  • 1088 XEL/XLD Owners and Builders's Topics
  • Atari BBS Gurus's Community Chat
  • Atari BBS Gurus's BBS Callers
  • Atari BBS Gurus's BBS SysOps
  • Atari BBS Gurus's Resources
  • Atari Lynx Programmer Club's CC65
  • Atari Lynx Programmer Club's ASM
  • Atari Lynx Programmer Club's Lynx Programming
  • Atari Lynx Programmer Club's Music/Sound
  • Atari Lynx Programmer Club's Graphics
  • The Official AtariAge Shitpost Club's Shitty meme repository
  • The Official AtariAge Shitpost Club's Read this before you enter too deep
  • Arcade Gaming's Discussion
  • Tesla's Vehicles
  • Tesla's Solar
  • Tesla's PowerWall
  • Tesla's General
  • Harmony/Melody's CDFJ
  • Harmony/Melody's DPC+
  • Harmony/Melody's BUS
  • Harmony/Melody's General
  • ZeroPage Homebrew's Discussion
  • Furry Club's Chat/RP
  • PSPMinis.com's General PSP Minis Discussion and Questions
  • PSPMinis.com's Reviews
  • Atari Lynx 30th Birthday's 30th Birthday Programming Competition Games
  • 3D Printing Club's Chat
  • Drivers' Club's Members' Vehicles
  • Drivers' Club's Drives & Events
  • Drivers' Club's Wrenching
  • Drivers' Club's Found in the Wild
  • Drivers' Club's General Discussion
  • Dirtarians's General Discussion
  • Dirtarians's Members' Rigs
  • Dirtarians's Trail Runs & Reports
  • Dirtarians's Wrenching
  • The Green Herb's Discussions
  • Robin Gravel's new blog's My blog
  • Robin Gravel's new blog's Games released
  • Atari Video Club's Harmony Games
  • Atari Video Club's The Atari Gamer
  • Atari Video Club's Video Game Summit
  • Atari Video Club's Discsuuions
  • Star Wars - The Original Trilogy's Star Wars Talk
  • PlusCart User's Bug reports
  • PlusCart User's Discussion
  • DMGD Club's Incoming!
  • DASM's General
  • AtariVox's Topics
  • Gran Turismo's Gran Turismo
  • Gran Turismo's Misc.
  • Gran Turismo's Announcements
  • The Food Club's Food
  • The Food Club's Drinks
  • The Food Club's Read me first!
  • The (Not So) Official Arcade Archives Club's Rules (READ FIRST)
  • The (Not So) Official Arcade Archives Club's Feedback
  • The (Not So) Official Arcade Archives Club's Rumor Mill
  • The (Not So) Official Arcade Archives Club's Coming Soon
  • The (Not So) Official Arcade Archives Club's General Talk
  • The (Not So) Official Arcade Archives Club's High Score Arena
  • Adelaide South Australia Atari Chat's General Chat & Welcome
  • Adelaide South Australia Atari Chat's Meets
  • Adelaide South Australia Atari Chat's Trades & Swaps
  • KC-ACE Reboot's KC-ACE Reboot Forum
  • The Official Lost Gaming Club's Lost Gaming
  • The Official Lost Gaming Club's Undumped Games
  • The Official Lost Gaming Club's Tip Of My Tounge
  • The Official Lost Gaming Club's Lost Gaming Vault
  • The Official Lost Gaming Club's Club Info
  • GIMP Users's Discussion


There are no results to display.

There are no results to display.


  • AtariAge Calendar
  • The Club of Clubs's Events
  • Atari BBS Gurus's Calendar

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start










Custom Status



Currently Playing

Playing Next

Found 19 results

  1. I thought it was about time that I create a goto place (no pun intended) for all things Camel99. So from now on I will put updates here. This update is my first Pong Game. It's a little quirky but it uses sound and sprites with no interrupts or multi-tasking. It's not that easy to win. The computer player is very crude but it make enough mistakes so that you can win. :-) Since I never spent much time writing games this has been educational for me. I have added a new simple word to CAMEL99 to create named character patterns. It's called PATTERN: "PATTERN:" words return the address (ie: a pointer) to the data that loads into VDP very fast using VWRITE. If you wanted to add PATTERN: to another Forth the code is: \ PATTERN: lets us define named character patterns \ usage: \ HEX 3C42 A581 A599 423C PATTERN: HAPPY_FACE \ 3C42 A581 99A5 423C PATTERN: SAD_FACE \ DECIMAL \ SAD_FACE 159 CHARDEF : PATTERN: ( u u u u -- ) CREATE >R >R >R \ push 3 values so we can reverse order , R> , R> , R> , \ compile 4 ints in VDP useable order ; The PONG code is in the spoiler. You have to load CAMEL99 with EA5 option and then paste PONG it into the emulator. When the codes finishes compiling type RUN. Latest version of CAMEL99 is on GitHub at the URL in the signature.
  2. In post #1 of fbForth—TI Forth with File-based Block I/O , I have updated the fbForth 2.0 Manual (a PDF with today’s date) and the blocks file, FBLOCKS (in a ZIP file with today’s date). The ZIP file also contains two disk images (90KiB and 400KiB) with the updated FBLOCKS file. The cartridge binaries for EPROM, Classic99 and MESS are still current except for FBLOCKS, which you can update from the above ZIP file. ...lee
  3. Those of us who have loved TI BASIC and TI Extended BASIC for these many years we have grown to love the unique way that we use the various sub-programs in the TI-99 system. How could we survive without CALL CLEAR, CALL SCREEN, CALL HCHAR and how about CALL MYSUBROUTINE like we do in XB? Awesome! It isn't bad enough that you have to do your math backwards in Forth but for some reason, implementations of the Forth programing language like TI-Forth, Turbo Forth and FBForth have completely failed to respect this noble tradition. Well I say "No More!" In my new CAMEL99 Forth I have added this staple TI-99 feature to the language. Here is how it works. Forth contains a large list of functions that for some reason are called WORDs. Not a lot of computer language savvy in that community I guess. I mean what's wrong with SUB-PROGRAM, FUNCTIONS, METHODS or MONADS? Some people just don't have the gift of creating good jargon. Everybody knows what "WORDS" are. Now if we want to CALL those so-called "WORDS" we need a way to find them. Fortunately FORTH has a SUB-PROGRAM called FIND. (See what I mean?) FIND takes a string argument and returns a true or false number and the actual string where the SUB-PROGRAM resides in the forth "DICTIONARY" or words. So that sounds like a good place to start. Now using a string in ANS/ISO Forth can be complicated because the people on the language committee could never agree on how to do strings one way. So there are byte counted strings, stack strings, text bytes in raw memory and if you want to you can even make strings like 'C' with a zero on the end. Make up my mind... please. Fortunately there is a FUNCTION called WORD that lets us parse out a word from what we type into the console, delimited by any character. Thank goodness it returns a simple string that we understand. We can pass that string from WORD to FIND and check the flag to see if we found the SUB-PROGRAM. That's great. But the string that it returns does not get us a way to CALL the Forth SUB-PROGRAM. It just gives us another string. Useless! Even worse it's actually not a REAL string. It's the ACTUAL address in memory where the string starts. They call it the "NAME FIELD ADDRESS". (NFA) Of course they do. So inside each Forth SUB-PROGRAM, right after the string, is a pointer to the machine code that needs to run to make the SUB-PROGRAM start. So we have to get that. This ADDRESS is called the "CODE FIELD ADDRESS" (CFA) and we can use a Forth FUNCTION to convert the NFA string to a CFA. So that is solved. But the CODE FIELD ADDRESS is not the address of the code we need. It is just the place where the CODE's address is stored. So now we need another CAMEL Forth sub-program ... I mean "WORD". The word we need is EXECUTE. EXECUTE calls a SUB-PROGRAM called FETCH which gets the contents of a memory location. Why Forth could not call it PEEK is more than I will ever understand. Once EXECUTE calls "FETCH" then and only then can EXECUTE run the SUB-PROGRAM. Of course in typical Forth "take the easy way" fashion, EXECUTE just uses one pathetic little assembly language instruction to run the SUB-PROGRAM. So it looks like we have all the things we need to make a "CALL" keyword for Forth and yet NOBODY in that world got off their butts to make it happen. Here is how it looks when we put it all together as a new definition. : CALL ( <TEXT> ) 32 WORD ( read the program text until char 32 ie: space char) ( pass output to FIND no variables in between Huh?) FIND ( FIND returns a string and a true/false flag) ( if the flag is zero stop with a useful message) 0= ABORT" * BAD NAME" NFA>CFA ( from the name string get the code field address) EXECUTE ( EXECUTE the code held in the CFA) ; So after all that coding we finally bring Forth into the TI-99 universe where we can write code that is a little more normal. (even though the parameters are still backwards) : MYPROGRAM CALL CLEAR 6 CALL SCREEN 9 9 102 12 CALL HCHAR ; CALL MYPROGRAM theBF PS After showing this to Lee Stewart he has "optimized" my CALL code to this. : CALL ; Looks to me like it defines a SUB-PROGRAM that does nothing... What? Like sub-programs are going to call themselves? These Forth people are REALLY weird. Happy April 1st
  4. OK...Here is @Willsy's “Hunt the Wumpus” ported to fbForth 2.0: As you can see, it took a bit more than “a few (very minor) changes”! The changes are all documented in the comments at the beginning, which you do not need to load for a working game. [EDIT: Bug fixes in GETROOM , DOMOVE , DOSHOOT and GAMELOOP .] ...lee
  5. LOL, did they repurpose that cover art from Heavy Metal magazine? Did they want to make sure only adults (with ID) could program in Forth? No really, zoom into that picture!
  6. I thought the forthies in the group would appreciate this http://xkcd.com/645/ made me laugh anyway :-)
  7. Hello everyone, i found a book named "Forth on the Atari " Learning by using Forth edit by E.Floegel. This book is writed by Winfried Hofacker.. I need found a dump image of forth language for learn reading this book.. If correct i read at end of book that i need this type of forth program: Learn-Forth – Subset of FigForth from HOFACKER (Order No.7053), disk-block based (without DOS) as well on cassette Power-Forth – Extended FigForth from HOFACKER (Order No.7055), disk-block based (without DOS) Maybe is possible found it? The book for me that in Forth laguage i am a novice seem good.. had more example also how use with atari 800 a electronic component by Forth language.. Thanks for all help that give me thanks! Herm
  8. I decided to move my explorations into TurboForth Assembler to a different thread (this one) rather than hijacking another thread. My post here (http://www.atariage....ost__p__2415039) alludes to my current project, viz., implementing Tursi's TMS9900-Assembler-coded 14-bit countdown timer (http://www.atariage....ost__p__2021341) using the TMS9901 Programmable Systems Interface and based on Thierry Nouspikel's code ("TMS9901" link at http://www.nouspikel...titechpages.htm). My two Forth words have the same name as Tursi's TMS9900 Assembler code: INIT01 to start the timer and READ01 to get its current value. My TurboForth Assembler code follows: ASM: INIT01 ( --- ) R12 R2 MOV, \ Save return address R12 CLR, \ CRU base of the TMS9901 0 SBO, \ Enter timer mode R1 $3FFF LI, \ Maximum value R12 INCT, \ Address of bit 1 R1 14 LDCR, \ Load value R12 DECT, 0 SBZ, \ Exit clock mode, start decrementer R2 R12 MOV, \ Restore return address ;ASM ASM: READ01 ( --- n ) R12 R2 MOV, \ Save return address R12 CLR, \ CRU base of the TMS9901 0 SBO, \ Enter timer mode SP INCT, \ Make space on stack to leave timer value *SP 15 STCR, \ Read current value (plus mode bit) and put on stack *SP 1 SRL, \ Get rid of mode bit 0 SBZ, \ Exit clock mode, decrementer continues R2 R12 MOV, \ Restore return address ;ASM Both words seem to compile OK. INIT01 appears to work, but I cannot tell for sure because executing READ01 causes a stack underflow, which baffles me. Any ideas as to what is wrong? ...lee
  9. In this lesson we will learn a few new arithmetic words, several words for stack manipulation and how to use them all in programming, i.e., defining new words. Before we do much more Forth arithmetic, let’s exercise our brains with some infix-to-postfix and postfix-to-infix conversions. Remember that infix notation is the same as algebraic notation and postfix is the same as RPN. Many of these exercises are based on or taken directly from Brodie’s Starting FORTH. Convert the following infix expressions to their postfix counterparts. Each answer is in the spoiler following the infix expression: 1. a + bc 2. a(b + c) 3. (a - 10b)/3 + c 4. 2a + 5b + (c + d)/3 5. 0.5ab/100 6. (a - b)/c Convert the following postfix expressions to their corresponding infix expressions: 1. a b - a b + / 2. a b 10 * / Now, let’s try to define some words that do calculations, using only the arithmetic operators we have learned to this point. Let’s define words that convert liquid measure in gallons, quarts, pints and fluid ounces to fluid ounces. We want to write out a phrase such as 2 GALLONS 3 QUARTS + 5 CUPS + 25 FLUID OUNCES + to put on the stack the result in fluid ounces. Starting with pints, we can define the next higher volume in terms of the next lower as follows: : FLUID ( -- ) ; a no-op, i.e., do-nothing visual place-holder word. : OUNCES ( floz -- floz ) ; a no-op visual place-holder word that indicates a value in fluid ounces is on the stack and unchanged by OUNCES . : PINTS ( pt -- floz ) 16 * ; converts pints to fluid ounces. : QUARTS ( qt -- floz ) PINTS 2 * ; converts quarts to fluid ounces. : GALLONS ( gal -- floz ) QUARTS 4 * ; converts gallons to fluid ounces. Note that the stack effects are comments in the above definitions for reminding us of each word’s function. You do not need to type them to have a functional definition. We can define the singular forms of the above words, with identical stack effects, in terms of the plural word names above as follows: : OUNCE OUNCES ; : PINT PINTS ; : QUART QUARTS ; : GALLON GALLONS ; These are now synonyms of the words included in each definition. Now we can write such phrases as the following: You can verify with a calculator that each result printed by . is the total liquid measure in fluid ounces of the quantities added before printing. Now, let’s define words to perform the arithmetic in the above six infix-to-postfix exercises. We will name each word as Exn , where n is the exercise number: 1. 2. 3. 4. 5. 6. We can only do integer arithmetic with the Forth we have learned thus far. Two more division operators can help us manage this a little better, viz., MOD (pronounced “mod”) and /MOD (pronounced “slash-mod”): MOD ( n1 n2 — rem ) leaves on the stack the remainder rem from n1/n2. /MOD ( n1 n2 — rem quot ) leaves on the stack the remainder rem and the quotient quot from n1/n2. As we discovered in the exercise definitions above, #4 is very difficult and #6 is impossible without some stack manipulation we haven’t yet learned. Here are some words that will help us to manipulate the stack: DUP ( n — n n ) duplicates the top stack cell. SWAP ( n1 n2 — n2 n1 ) reverses the top two stack cells. OVER ( n1 n2 — n1 n2 n1 ) copies the second cell to the top of the stack. ROT ( n1 n2 n3 — n2 n3 n1 ) rotates the third cell to the top of the stack. DROP ( n — ) drops the top cell from the stack. EX4 can now be defined as Here is a commented version of EX4 to explain a little better how it works. The running contents of the stack are shown in comments as “stack:...” when the stack is changed by a line of code: and EX6 is now tractable as and the commented version to monitor the stack: Let’s try our hand at defining words for these two formulas for converting between Fahrenheit (°F) and Celsius (°C) temperatures: F = 9C/5 + 32 C = 5(F - 32)/9 Let’s define TC>TF to do the Fahrenheit-to-Celsius conversion (formula #1) and TF>TC for the opposite conversion (formula #2). Try it yourself before opening the spoiler below to see one way to do it: : TC>TF : TF>TC Now let’s improve these words to round to the nearest degree using /MOD instead of / so we can work with the remainder of the integer division. We also need to expand the factors 9/5 and 5/9 to 18/10 and 10/18, respectively, so we can halve the divisor and still get an integer: : TC>TF : TF>TC Here are commented versions for clarity: : TC>TF : TF>TC Be sure to try some negative temperatures. Compare the results with a calculator. Anything wrong? The following fbForth 2.0 word will help us craft a better rounding solution: SGN ( n — -1|0|1 ) leaves on the stack the sign (-1 or 1) of n or 0 for n = 0. The symbol ‘|’ in the stack effects means “or” and separates possible results, only one of which will be left on the stack. To get the above temperature-conversion words to round properly in both the positive and negative directions, we need to change the sign of the half-divisor term to match the remainder given by /MOD . Because SGN consumes the number it is testing, we need to DUP it before we hand it off to SGN . All we need to do now is to multiply the half-divisor term by the sign, add the result to the remainder term and divide again. This time we don’t care about the remainder. This quotient will be our rounding term of 1, -1 or 0, which, when added to the previous integer result, will give us our correctly rounded conversion: : TC>TF : TF>TC And commented versions for clarity: : TC>TF : TF>TC That’s all for this session. Please, feel free to ask questions and make suggestions; and certainly, let me know of any mistakes you find.
  10. I think we need a thread like the development thread for just the software we make. I have found it a 'hit or miss' when trying to keep up with the various games, apps, virtual-cartridges people are coming up with on this board. We could put the beta and completed versions on the thread. Be glad to monitor it. Just a thought.
  11. TheBF

    Camel Forth V.5 Demo

    From the album: CAMEL99 Forth

    Video showing 2 different ways to fill the screen with numbers 0 to 9.

    © Brian Fox Markham Canada, 2017

  12. After 30 years of wondering I finally got around to creating a Forth compiler for the TI-99 where the top of stack (TOS) is maintained in a register. The literature said this would speed it up by about 10%. I used a DOS Forth system to create the cross-compiler to the build the TI-99 compiler so it was painful debugging both ends at the same time. (old brain hurts) I cross-compiled Brad Rodriguez's Camel Forth for the high level Forth words and wrote 105 Assembler primitives with hints here and there to the hard stuff from TI MSP430 Camel Forth and I had to look at Turbo Forth to help find a couple of gotchas with the 9900 instruction set. Sincere thanks to Willsy and Brad. Anyway the answer is in.,, kind of sort of. Using Willys's excellent and highly optimized Turbo Forth as the benchmark for excellence I did a little comparison. Turboforth uses the PAD RAM at >8300 to hold many simple code routines so they run very fast in that zero wait state memory. To even begin to come close to Turbo Forth I found out I also had to put the Forth thread interpreter there along with branching and I stuck the literal run-time routine there as well. After that the only optimizing approach I used was this TOS thing The TOS caching is a mixed blessing. For routines that take one input on the stack and produce one output like 1+ 2+ 2/ 2* @ [email protected] etc... it is about 40% faster. Very cool. For operations that take two inputs and generate one output or no output on the stack, ( ! C! + - * etc.) refilling the TOS can eat up all of the benefit on the 9900. And for operators that need to make extra space on the stack for an output, the TMS9900 needs 2 instructions so they are actually slower because you have to push the TOS register onto the stack to make room for the new thing. (DUP OVER etc.) FYI: - my empty DO/LOOP structure runs the same speed as Turbo Forth so the test is truly comparing the math operations. - Tests were run on Classi99 emulator under Windows 10 64bits (my real iron is in a box with a defective 32K memory card) Test 1 tests all the routines Turbo Forth has in PAD Ram and the others as well, so it's mixed. Test 2 is head to head TOS vs PAD RAM optimization. Test 3 is TOS vs Forth operators that have no PAD RAM optimization. We can see in test 3 the we get about 8% improvement not 10%. The surprise for me was test 2 because the speedup was not suppose to be as fast as zero wait state ram but it seems the combination of everything netted out to the same result. Weird. In many other ways Turbo Forth is still faster by virtue of hand coding so much of the internals, but this demonstrates the TOS on math operations. Now I have to stop doing this for a while. (addictions are hard to kick) PS. I noticed I did not include NIP and TUCK but that's for another day. PSS This means Turbo Forth 3.0 can be 8% faster. Just one more re-write Willsy :-) theBF HEX : OPTEST \ mixed 1000 0 \ *OPTIMIZATION METHOD* DO \ CAMEL99 Turbo Forth \ ---------------------- AAAA ( lit) \ HSRAM HSRAM DUP \ TOS HSRAM SWAP \ TOS HSRAM OVER \ TOS HSRAM ROT \ TOS -- DROP \ TOS HSRAM DUP AND \ TOS -- DUP OR \ TOS -- DUP XOR \ TOS -- 1+ \ TOS HSRAM 1- \ TOS HSRAM 2+ \ TOS HSRAM 2- \ TOS HSRAM 2* \ TOS -- 2/ \ TOS -- NEGATE \ TOS -- ABS \ TOS -- + \ TOS HSRAM 2 * \ TOS HSRAM DROP LOOP ; \ CAMEL99: 4 5 secs \ TurboForth 4.7 secs \ (Empty DO/LOOP are same speed) : OPTEST2 \ only HSRAM VS TOS 2000 0 \ *OPTIMIZATION METHOD* DO \ CAMEL99 Turbo Forth \ ---------------------- AAAA ( lit) \ HSRAM HSRAM DUP \ TOS HSRAM SWAP \ TOS HSRAM OVER \ TOS HSRAM DUP AND \ TOS HSRAM DUP OR \ TOS HSRAM 1+ \ TOS HSRAM 1- \ TOS HSRAM 2+ \ TOS HSRAM 2- \ TOS HSRAM + \ TOS HSRAM 2 * \ TOS HSRAM DROP \ TOS HSRAM DROP \ TOS HSRAM LOOP ; \ CAMEL99: 6.4 secs \ TurboForth 6.4 secs HEX : OPTEST3 \ TOS versus conventional Parameter stack 3000 0 \ *OPTIMIZATION METHOD* DO \ CAMEL99 Turbo Forth \ ---------------------- AAAA \ HSRAM HSRAM BBBB \ HSRAM HSRAM CCCC \ HSRAM HSRAM ROT \ TOS -- AND \ TOS -- OR \ TOS -- DUP XOR \ TOS -- 2* \ TOS -- 2/ \ TOS -- NEGATE \ TOS -- ABS \ TOS -- DROP \ TOS -- LOOP ; \ CAMEL99: 7.5 secs \ TurboForth 8.13 secs
  13. Mark (or anyone)... I cannot find any documentation about using the TurboForth word JOYST except in the TF v1.1 Release Notes: JOYST ( jstick# -- value) modified to invert the returned value, making decoding much simpler. JOYST also resets the screen blanking counter in the console interrupt routine to prevent screen blanking. Unfortunately, this is not very helpful to me. In TI Forth, three values are left on the stack (ASCII, xpos, ypos). I have no idea how to use TF's word. I cannot even get it to respond with a value other than 0 when I use it in a loop in the emulators for joystick #1, i.e., 1 JOYST . I am trying to use the keyboard emulation of joystick #1 (Q,W,E,R,S,D,Z,X,C). ...lee
  14. I am starting this thread to collect various examples of bitmap graphics programming in fbForth 2.0. This first example is a quick-and-dirty joystick drawing program, JDRAW , ported from the program of the same name I wrote four years ago for TI Forth in post #48 of thread, TI FORTH Version 3.0 dated October 20 1982. As I stated then, it is a pretty useless program except as a demo and proof of concept. It uses the CRU mode of JOYST for joystick-only use. There is a three-choice menu accessed with the fire button. The choices are P—Toggle pen up/down [blue pen = pen down; white pen = pen up] D—Toggle draw/erase [ solid pen = draw mode; hollow pen = erase mode] Q—Quit program The joystick moves the pen around the display screen. There is much that could be done to make it more useful. One such thing would be to provide finer control over the pen—reaction to joystick movement is too fast for any useful drawing. Another would probably be to dispense with the menu and use the fire button for pen-up/pen-down. But, that leaves managing draw/erase mode, which would probably require using the JOYST word in keyboard (KSCAN) mode. Anyway, here is the fbForth 2.0 source code for JDRAW : I will add a blocks file, later. For now, you can paste this in Classic99 at the command line of fbForth 2.0. Start the program by typing: JDRAW ...lee
  15. This lesson will discuss more of the details of RAM organization, working with the stack and some minimal Forth programming. The 32 KiB expansion RAM on the TI-99/4A is organized as follows in fbForth 2.0: The 8 KiB lower RAM (2000h – 3FFFh) contains four fbForth block buffers, low-level Assembly Language support, system global variables (termed “user variables”) and the return stack. You will notice here that hexadecimal numbers in this discussion (not in actual Forth code!) have a trailing ‘h’. The return stack starts at the top of this space at 3FFEh and grows downward toward the low-level support code, which currently ends at 3A03h. This allows 766 cells for address storage for deeply nested code. Colon ( : ), introduced in the last lesson, makes extensive use of the return stack. Your code can make use of the return stack as well; but, you must be very, very careful when you do, that you do not interfere with the return scheme of fbForth. In a later lesson we will discuss how to safely use the return stack because it certainly can be useful. The 24 KiB upper RAM (A000h – FFFFh) is almost entirely free for your Forth programming pleasure. This is due to the fact that the entire resident dictionary of fbForth 2.0 resides in the 32 KiB ROM of the cartridge. The last word of the resident dictionary is TASK and resides at A000h for reasons that will be explained in a later lesson. The next available address is A00Ch. This is the beginning of the user-definable dictionary. Any words defined after this point are still part of the dictionary and, as a result, become part of the language. This is what makes Forth extensible. The top of memory in the upper 24 KiB area contains the Terminal Input Buffer (TIB) and the base of the parameter stack at FFA0h. This means that all but 108 bytes of the upper 24 KiB area is available for your programming. This, of course, includes the parameter stack, which grows downward toward the dictionary, which grows upward toward the stack. Now is a good time to elaborate on a comment Owen left on the last lesson, viz., verbalizing or pronouncing Forth words. Forth was intended to be a language you could speak. That is pretty much why Forth functions, routines, constants and variables are called “words”. I will try to remember to include the usual pronunciation of standard Forth words as we discuss them. A very good source for such pronunciations is Derick and Becker’s FORTH Encyclopedia: The Complete FORTH Programmer’s Manual, 2nd Edition. The words appear in ASCII order, so they are easy to find. Each of the entries includes the word’s pronunciation. An example from the last lesson is SP! , which is usually pronounced “S-P-store”. The “SP” part happens to refer to the stack pointer, which is why I had said “stack pointer store”. Another example, as Owen mentioned, is “dot-quote” for ." and “quote” for " . Most words’ pronunciations are not difficult to figure out; but, there are a couple of heavily used words that are not obvious. One is @ , which is pronounced “fetch” because it pops an address from the stack and fetches its contents to the stack. Another is ! , which is pronounced “store”. It requires two numbers on the stack: the number to store and the address in which to store it. We will discuss these in greater detail ere long. We turn our attention, now, to working with the stack. As mentioned last time, it operates in a LIFO mode. To show you how it works, we will use . and a new word, .S (pronounced “dot-S” and means “print stack”). .S will non-destructively print the stack contents from the bottom up (left to right), with ‘|’ representing the bottom of the stack. Recall that . pops the top number off the stack and prints it: You will see that the system response of “ok:5” displayed after .S is executed shows the stack to have the same depth as before it was executed. Notice that the last of the five numbers entered is on top of the stack, that it is the first one popped and printed by . and that the system response shows the depth to be one less after each . . The last line demonstrates what happens when you execute a word requiring a number on the stack but with nothing on the stack. The number 11776 (2E00h) printed is significant because the bottom edge of the stack is the start of the TIB and the last thing entered at the terminal (console) was ‘ . ’, which has an ASCII code of 2Eh. A Forth convention when defining or listing words is to show the state of the stack before and after the word executes. The stack effects (also, stack signature) are indicated by showing within parentheses what the word expects on top of the stack before it executes to the left of an em-dash (—) (or two or three dashes [--]) and what it leaves on the stack to the right. Also, the most accessible number is always on the right on either side of ‘—’, which represents execution of the word. For example: ! ( n addr — ) shows that the stack effects of ! , which requires the storage address addr to be on top of the stack and the number n, which will be stored at addr, below it. The absence of anything to the right of the execution indicator (—) shows that ! leaves nothing on the stack. Let's do a little math with the stack. We will start with the basic four: addition, subtraction, multiplication and division. Here are those definitions with their stack effects: + ( n1 n2 — sum ) pronounced “plus” - ( n1 n2 — diff ) pronounced “subtract” * ( n1 n2 — prod ) pronounced “times” / ( n1 n2 — quot ) pronounced “divide” Each of these operators requires two numbers on the stack and leaves the result on the stack when it is done. Below are examples of each operation, showing the result printed with . : As you type the above at the terminal, you will see that the operator is after the numbers it operates on. This is an example of postfix notation or RPN (Reverse Polish Notation). You are probably more familiar with infix (algebraic) notation: 1 + 2 = 3 where the operator is between the two numbers it operates on. The postfix nature of Forth is the highest hurdle you will likely need to get over. Words in Forth can certainly be defined in an infix way; but, postfix is more efficient and easier to implement. An interesting bit of history regarding RPN: Reverse Polish Notation implies that there is a Polish Notation, which, of course, there is. Polish logician Jan Łukasiewic (yahn woo-kah-SHEH-vitch) invented prefix notation to simplify a branch of mathematical logic. The operator precedes its two operands in prefix notation. It became known as Polish Notation (PN) due to the nationality of Łukasiewic. Quite naturally, when postfix notation arrived on the scene with the exact opposite form, it became known as Reverse Polish Notation (RPN). At the top of this lesson, we discussed memory organization, stating that virtually all of the available programming memory is one chunk between the top of the parameter stack and the most recently defined word in the dictionary. Each of these locations is readily available with resident fbForth 2.0 words: [email protected] ( — addr ) pronounced “S-P-fetch”; leaves on the stack the address of top of stack HERE ( — addr ) pronounced “here”; leaves on the stack the address of next available dictionary location The available RAM is the difference between these two addresses. Since the stack is at the higher address, we want to subtract HERE from the top-of-stack address: We can make a couple of useful definitions from this: : SIZE ( -- n ) [email protected] HERE - ; : .SIZE ( -- ) SIZE . ." bytes free" ; The first one leaves the size in bytes of free RAM between the top of the stack and HERE. The second prints that number followed by “bytes free”. You may have noticed that I slipped in another word in the definitions above, viz., ( . Pronounced “left paren”, it begins a comment, which is terminated by ‘)’. Comments are ignored by the text interpreter. Obviously, the comments above are not necessary for the definitions to work. You can enter the above definitions without them. They help us to remember what the words do. We will make it a habit to include the stack effects in this way when we actually begin storing our new words in a blocks file a lesson or two hence. We will conclude this lesson by defining one more useful word. CLS is a resident fbForth word that clears the screen but does not move the cursor. To also move the cursor to the top of the display screen, we will define PAGE for which we need another fbForth word that sets the cursor: GOTOXY ( x y — ) sets the cursor to the x-y coordinates on the stack. The upper left corner of the display screen is at x = 0, y = 0. To show GOTOXY in action, we will place the cursor somewhere in the middle of the screen and print an ‘X’ there: And, now, our definition of PAGE : : PAGE ( -- ) CLS 0 0 GOTOXY ; clears the screen and sets the cursor to the top left corner of the display screen. Here is the screen after the definition and just before execution: and after execution: That’s it for this session. We will do more stack manipulation and programming next time.
  16. All... We have had quite a discussion on the YaHoo! TurboForth forum regarding floating point math and transcendental functions using it. I want to bring some of it over here, particularly because I am having trouble posting there. Rob Van Orden, Willsy and I have been going at the TF code pretty hot and heavy. In a bit, I will post the TF BLOCKS file we have been working on. Right now, a glass of wine and my Love beckon! Feel free to jump in anytime! ...lee
  17. Pardon my naiveté, but I have a question about the transfer block for the diskette level 1 formatting subprogram (11h). The docs (GPL Interface Specs for 99/4 Disk Peripheral) say the MSN of 834Ch for the DSR version should be 1 for double-sided formatting, but are a little confusing for when 2 should be used, in particular, for density. Is that any density greater than single? More generally, does anyone from experience reading this have detailed advice about exactly what diskette formats can be written with which DSR version numbers in this nybble (presuming, of course, an appropriate version of the DSR is in place)? For example, what happens if the transfer block has DSR version = 0, Density = 2 and No. of Sides = 2? ...lee
  18. This was the forth that was used to build the game Universe from Omnitrend I won a manual, copy of starting forth, disk and quick reference card
  19. http://toddbot.blogspot.com/2012/04/why-forth-still-matters-in-this.html
  • Create New...