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


Forums

  • Atari Systems
    • Atari 2600
    • Atari 5200
    • Atari 7800
    • Atari Lynx
    • Atari Jaguar
    • Dedicated Systems
    • Atari 8-Bit Computers
    • Atari ST/TT/Falcon Computers
  • Gaming General
    • Classic Gaming General
    • Classic Computing
    • Modern Gaming
    • Prototypes
    • Arcade and Pinball
    • Emulation
    • Hardware
    • Gaming Publications and Websites
    • International
  • Marketplace
  • Community
  • Game Programming
  • Site
  • Classic Gaming News
  • 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

Blogs

There are no results to display.

There are no results to display.

Calendars

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

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Website


Facebook


Twitter


Instagram


YouTube


eBay


GitHub


Custom Status


Location


Interests


Currently Playing


Playing Next

Found 22 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. 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
  4. 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
  5. I thought the forthies in the group would appreciate this http://xkcd.com/645/ made me laugh anyway :-)
  6. 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!
  7. 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
  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. All... I have a first draft (attached) of my updated version of the (now finished---see later or click link-->) TI Forth Instruction Manual in PDF format. I am working on it in Open Office Writer (ODT format), but it won't look right if someone reading it does not have the fonts I used. I think the PDF will work better. I have elaborated parts of the manual, but I have not started an index, yet. One problem with the indexing in OOO Writer is that I have not yet figured out how to sort the index by ASCII codes. Writer wants to put non-alphabetics at the end and I want them as the TI FORTH Glossary has them, i.e., in ASCII order. Anyway, I am very interested in any feedback on this draft, particularly where I have added or changed information and whether you think an index would be useful. ...lee
  10. 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.
  11. This is the first of several tutorials to help those new to Forth, fbForth 2.0 in particular, to understand the language and its programming environment, as well as to gain some facility with it. fbForth is based on TI Forth, which was derived mostly from FIG-Forth with some influence from Forth-79. There are more recent Forth standards; but, compatibility with TI Forth was the prime concern. The biggest difference between TI Forth and fbForth is that fbForth is a file-based system, whereas TI Forth reads/writes directly from/to disk sectors without regard to any file structure. This is dangerous for the health of the disk and the user, especially, if you were to inadvertently use a disk with files on it for other systems. It also makes it difficult to exchange programs. Not only does fbForth coexist with as many unrelated files as will fit on a disk, you can create many different blocks files on the same disk as long as there is room. A TI Forth disk cannot contain anything but Forth blocks. I suppose that is more than sufficient for preamble. Let’s get on with learning fbForth. To operate the fbForth 2.0 System, you must have the following equipment or equivalent: TI-99/4A Console Monitor fbForth 2.0 Module (see this forum thread’s post #1 to get yours: fbForth—TI Forth with File-based Block I/O ) Peripheral Expansion Box (PEB) with 32 KiB Memory Expansion Disk Controller with 1 or more Disk Drives RS232 Interface (optional) [*]Printer (optional) If you wish to work through these tutorials but do not have this equipment or equivalent (CF7+ or nanoPEB, which substitutes for a PEB with the first three PEB items above), all of the software and firmware are available in the above-referenced thread for the Classic99 and MESS emulators. I also can supply the same for CaDD Electronics’ PC99 emulator, if you need it. It is a good idea to have a copy of fbForth 2.0: A File-Based Cartridge Implementation of TI Forth (the manual—available in the above forum thread) for reference, especially for looking up commands (Forth words—more below) in the glossary (Appendix D). Please note that the glossary is in ASCII order, which is listed at the bottom of every glossary page. Also, if you have a copy of the first edition of Leo Brodie’s excellent beginner’s book on Forth: Starting FORTH, Appendix C of the manual cross-references conflicts with fbForth 2.0. After powering up and selecting “fbForth 2.0”, you will be presented with one of these screens: The system blocks file is FBLOCKS and must be in DSK1 for the first screen to display. If fbForth does not find it there, the second screen displays. fbForth will still work just fine. You just won’t be able to display the menu of loadable utilities with MENU until you make FBLOCKS the current blocks file, which you can do by typing the following at the console’s flashing cursor if FBLOCKS is in DSK2, say: USEBFL DSK2.FBLOCKS1 LOAD Notes about the welcome screen: The first two lines and the last line of the welcome screen appear regardless of the presence of FBLOCKS. The version number of the cartridge includes the revision number after the ‘:’. The line beginning with “FBLOCKS mod:” comes from block #1 of FBLOCKS and will always reflect the current date of the system blocks file, FBLOCKS, which is always kept up to date in the above forum thread. Commands in Forth are called “words”. You will note that Forth words included in the normal text of these tutorials appear in boldface and are surrounded by spaces. This may look awkward when the space after a word precedes a comma, period or similar punctuation mark; but, since those punctuation marks are also Forth words, this practice avoids ambiguity. Speaking of spaces around words, that is how the Forth text interpreter ( INTERPRET ) knows it has the next word to look up in its dictionary (linked list of already defined words). It searches the dictionary from the most recently defined word to the very first word defined. In fbForth, that word is EXECUTE . See what I did there? EXECUTE has a space after it and it’s before a period. You are in the hands of the Forth text interpreter in two places, viz., at the console’s blinking cursor and when a block is loaded by the word LOAD . The input stream is viewed by the interpreter as a series of tokens separated by one or more spaces. If the interpreter finds the word, it executes the word and gets the next token. If the interpreter cannot find the token as a word in the dictionary, it checks to see if the token can be converted to a number in the current radix (number base). If it can, it pushes that number onto the parameter stack, which is often termed the data stack or, simply, the stack. The parameter stack, by the way, consists of a stack of cells, much as a stack of plates in a cafeteria, with the same restriction: You can only readily remove (pop) the top plate, i.e., the last cell on the stack is the most accessible and thus the first one popped off. This Last_In_First_Out situation is known as LIFO. Furthermore, in fbForth, a cell is 16 bits or 2 bytes wide. In computer parlance, 2 bytes constitutes a word; but, to avoid confusion with talking about Forth commands as words, we will generally avoid using “word” to mean “2 bytes”. Finally, if the token is not a word in the dictionary and it cannot be converted to a number, the interpreter gives up and issues an error message that repeats the word it could not find followed by a question mark. It also clears the stacks (parameter stack and return stack, about which more later) and leaves two numbers on the parameter stack to aid in finding where in the input stream the error occurred. These numbers are the contents of user variables IN (the position in the input stream immediately following the token causing the error) and BLK (the block number being interpreted—0 for console input). These are mostly just irritating when you are typing; but, when loading a block that aborts with the error report just described, it is very handy because you can type WHERE to put you into the editor with the cursor at the error. We will talk more about the editor in another lesson. Otherwise, you may just want to type SP! (stack pointer store) to clear the parameter stack. After you finish entering one or more successfully interpreted words and/or converted numbers with <ENTER>, the interpreter will display “ ok:n” to let you know its success. The ‘n’ after the colon is the depth of the parameter stack, i.e., how many numbers are currently on the stack. Here are a few lines typed at the console: The first line is from just tapping <ENTER>. Everything is OK with nothing on the stack. The second line pushes ‘4’ onto the stack and indicates all is well with one number on the stack. The third line pops and prints ( . ) the number, showing the stack as now empty. The last line obviously was not understood by the interpreter, hence the error message. Let’s wind this lesson up with showing you the most common way to define a new word in Forth. The defining word we speak of is : . : starts a high-level Forth definition, which is terminated with ; . The first token that must follow : is the name for the new word. fbForth is case-sensitive. “HELLO” is different from “hello”. We will use in our definition the word that means “print string”, namely, ." . ." accepts any characters into the string except for " , which is the terminator. As soon as it sees the " , it prints the string: We will define the word HELLO and add CR to the definition before and after the print-string code. This will put the cursor at the beginning of the next line each time it is executed. Typing the newly defined word, HELLO , will execute its contents: That’s all for now.
  12. 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.
  13. 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

  14. 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
  15. 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
  16. 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
  17. 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.
  18. 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
  19. Wow! It's been a really long time since I've done much of any significance with the TI99-4A! I have nearly 80 cartridges, many of which are used by my grandkids on a regular basis when they come over. The productivity software/cartridges (TI BASIC, TI Extended BASIC, TI Writer, TI Multiplan, Editor/Assembler, Terminal Emulator II, TI Logo II and TI FORTH) have seen little use except for TI BASIC until very recently. I have often used TI BASIC for simple math problems like figuring trigonometric solutions for various projects around the house because I could fire up the TI quicker than going upstairs to boot up one of the PCs. I might need the hypotenuse of a right triangle to lay out the paint lines on the grass of the volleyball court. Recently, however, after noticing to my delight an unexpected presence on the Internet of TI99ers, I was inspired to pick up a couple of projects I had long ago allowed to languish for 20 odd years! They both had to do with TI FORTH. One was to clean up and make easier to use with an index and anything else I could use to make it better, the TI FORTH Instruction Manual. The other was to finish a FORTH program I had started that was to solve a problem with a unique Social Security Number (SSN), viz., using the digits 1-9 only once (no 0, of course), construct a SSN with the growing number evenly divisible by the position number of the last digit. For example, 123 needs to be evenly divisible by 3 (it is) and 1234 needs to be divisible by 4 (it is not, but 1236 is), etc. I have finished the FORTH problem and am well on my way to polishing up the TI FORTH Instruction Manual. If there is any interest, I will post the FORTH solution (I may do it anyway!). When I am finished with the TI FORTH Instruction Manual, I will post it, as well. Also, I am certainly interested in whether anyone else is doing anything with the original TI FORTH on the 99-4A. Later... lee
  20. 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
  21. http://toddbot.blogspot.com/2012/04/why-forth-still-matters-in-this.html
  22. 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
×
×
  • Create New...