Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by TheBF

  1. The code is beginning to look a little more like normal Forth. It still needs a few magic incantations but it's getting closer to normal Forth (if there is such a thing) :) \ fibonacci benchmark in Camel Forth COMPILER \ Set up environment NEW. HEX 2000 ORIGIN. OPT-OFF \ Machine Forth does not have DO LOOP so we use a library INCLUDE DSK2.DOLOOP \ Machine Forth doesn't normally have ROTate, we have to create one. TARGET : ROT ( n1 n2 n3 -- n2 n3 n1) [ 2 (SP) R0 MOV, *SP 2 (SP) MOV, TOS *SP MOV, R0 TOS MOV, ] ; : FIB ( n -- ) 0 1 ROT 0 DO OVER + SWAP LOOP DROP ; \ 42.6 seconds using Expansion RAM stacks \ 35.7 SECONDS using FAST RAM stacks \ 174 bytes PROG: MAIN \ Assembler instructions and directives must be interpreted [ 0 LIMI, HEX 8300 WORKSPACE 83EA RSTACK 8400 DSTACK DECIMAL ] \ turn compiler back on 1000 0 DO I FIB DROP LOOP [ 0 @@ BLWP, ] END. COMPILER SAVE DSK2.FIBONACCI
  2. And at this stage of maturity it is a good target for it's own compiler.
  3. It is a very cool piece of music nevertheless. I think I hear 4 voices plus a little percussion thing. Hard to replicate exactly on our machines but with some clever re-arranging we might be able to get the general effect. I might spend some time on Sibelius to notate it first. What is the original source? Is it public domain?
  4. Here is an example where you really see the impact of the extra work the 9900 has to do to maintain a stack. Using the stack to transfer a register to a variable takes a lot of extra time using the Forth stack. Having inline Assembler is the solution is so handy. fornext-inline-asm.mp4
  5. One day, MACHFORTH will be a thing I have been doing some tail chasing with this project since I started out just trying to make it compile runnable code. However now I want it to be a useable Forth programming system for TI-99. There is no standard way for cross-compiled Forth to operate so I am feeling my way along. I spent some time (ok a lot of time) re-thinking how to make this Machine Forth look more like normal Forth. The problem is mostly about interpreting literal numbers correctly during interpretation and during compilation. In version 1, I used the # operator to compile the code to put a literal into the code. I think Chuck Moore resorted to this as well. (But it looks kind of ugly) The solution was to create a "state" variable for the cross-compiler as Forth does internally. (DUH!) The thing that needed changing in the Forth REPL was the code that compiles a literal number. Since Forth interprets and compiles it needs to either: Compile some code into the program image that safely puts a number onto the top of the Forth data stack when the program is running. Interpret the number which for Forth means put in onto the top of compiler's data stack and just leave it there. The determining control is the state variable. In Camel99 Forth I have vectored the REPL (read evaluate print loop) to use the LISPer's term. So I re-wrote the REPL loop and changed one line that deals with compiling the literal number. VARIABLE XSTATE \ CROSS-COMPILER state variable : LIT, ( n -- ) XSTATE @ IF \ IF we are compiling machine Forth code TOS DPUSH, \ *SmartDUP does not work here. TOS SWAP LI, \ compile n as a literal number into R4. THEN ; : <MFINTERP> ( i*x c-addr u -- j*x ) \ machforth compiler interpret loop 'SOURCE 2! >IN OFF BEGIN BL WORD DUP [email protected] ( -- addr len) WHILE FIND ?DUP IF ( it's a word) 1+ STATE @ 0= OR IF EXECUTE ELSE COMPILE, THEN ELSE ( it's a number) COUNT NUMBER? ABORT" MF: Not recognized" LIT, ( This is the only real difference ) THEN DEPTH 0< ABORT" MF: Compiler stack underflow" REPEAT DROP ; I can vector the REPL loop from normal Forth numbers or for cross-compiling numbers. The place to do that is in the directives COMPILER which needs normal Forth numbers and TARGET which is used when we are compiling to the "target" image. But of course that leads to a minor complication when writing Assembly language inside a colon definition because Forth assembler is interpreted. (No it really is) :) This is easily remedied with the [ ] operators which turn off and turn on the compiler like this: : BYE [ 0 LIMI, 83C4 @@ CLR, 0000 @@ BLWP, ] ; So that's not too hard to endure. Another issue that came up is when I want to create Assembler macros but I think have a solution since I now have a command FORTH-REPL so I can over-ride the MACHFORTH-REPL anytime I need to. So here is what a test program looks like now.
  6. But if you are "missing the link" what could you do? You would need to make an editor loop like one does in other language I guess. You would put KEY() in a loop with control key values doing GOSUBs to various cursor control routines and placing valid ascii chars on the screen at the cursor position. The most difficult thing for XB would probably be inserting and deleting although you might be able to use SEG$() and DISPLAY AT() to good effect but it might still be painful on a really long string. It's pretty good with this string length. 100 A$="NOW IS THIS TIME FOR ALL GOOD MEN TO COME TO THE AID OF THEIR COUNTRY. I don't know what happens when the string gets very long? " 110 CALL CLEAR 120 FOR I=LEN(A$)TO 1 STEP -1 130 DISPLAY AT(1,1):SEG$(A$,I,LEN(A$)-I) 140 NEXT I 150 GOTO 110
  7. "It takes nine months to have a baby no matter how many women you put on the job." (Fred Brookes, The Mythical Man Month) Well actually my newest granddaughter arrived in 8 months plus one week, about 2 weeks ago and she is really cute. Unlike little baby Ivory, my documentation for the linker took longer than it should but here it is. I included @FarmerPotato 's disk with some additions of my own to aid in the getting used to this beasty. I have been testing on an unreleased version of Camel99 (2.68F) but it should work on the latest released version. Maybe it is of some use to someone out there. :) Erik I believe your original question was because you have some bit map graphics code that you want to run under Forth. If you want to post it here I can take a run at making it work (if it assembles with the standard TI Assembler) LINKER99.zip
  8. Just curious about what compiler this is and could it be some kind of un-intended optimization bug?
  9. Sometimes maintenance is worthwhile. I had hacked together a version of -TRAILING like this. (-TRAILING removes trailing spaces from a string) CODE -TRAILING ( addr len -- addr len') *SP W MOV, \ DUP addr in W TOS W ADD, \ add len R1 2000 LI, \ R1 holds the space character W DEC, \ w=address of last char BEGIN, *W R1 CMPB, \ compare to ascii >20 EQ WHILE, W DEC, \ move back 1 char TOS DEC, \ dec len in TOS REPEAT, TOS 0 CI, 1 JGT, TOS CLR, NEXT, ENDCODE Looking at it I didn't like having two DEC instructions inside the loop and I really didn't like the negative length test at the end. This is about 13% faster. It seems to test solidly. HEX CODE -TRAILING ( addr len -- addr len') *SP TOS ADD, \ add len TOS DEC, R1 2000 LI, \ R1 holds the space character BEGIN, *TOS R1 CMPB, \ compare to ascii >20 EQ WHILE, TOS DEC, \ move back 1 char REPEAT, *SP TOS SUB, TOS INC, NEXT, ENDCODE
  10. Have the heads, pinch-roller and capstan been cleaned?
  11. Obsessed with SAMS I have managed to take out 4 more bytes per definition. Two in SAMS memory and two in the forth Dictionary entry. I removed the GOTO SAVEHERE line and replaced it with FARSEMIS. This is a run-time exit from a SAMS definition so it can go in SAMS memory at the end of a definition. The caller's IP address is pulled from the return stack so that's that. Changing the dictionary pointer is a compile time complication so that is handled by ;FAR when we compile a new SAMS word. My ultimate goal here is to get the entire FAR: definition living in SAMS memory and then modify FIND to search through SAMS banks first in declining order before searching Forth. This will make FAR: definitions look similar to ANS Forth wordlists but we can have a lot more of these SAMS lists than wordlists. I only have room for 9 in the kernel. I have also moved my INCLUDE line buffer into high RAM. I was using PAD but when INCLUDEing into a SAMS block PAD is in the SAMS memory and so it prevents using the last 127 bytes of the SAMS bank. The other thing that is interesting is how compact headless Forth code is. All these files compiled into 4K with 380 bytes to spare. Of course there was another 1800 bytes of header code over in CPU RAM. (I need to make a way to leverage this idea to create headless programs that can be saved as EA5 images.) DECIMAL 240 SETBANK HEX INCLUDE DSK1.ELAPSE INCLUDE DSK1.UDOTR INCLUDE DSK1.ANSFILES INCLUDE DSK1.CATALOG INCLUDE DSK1.DIR INCLUDE DSK1.MORE INCLUDE DSK1.BUFFER INCLUDE DSK1.COMPARE INCLUDE DSK1.CASE INCLUDE DSK1.VALUES INCLUDE DSK1.TRAILING INCLUDE DSK1.SYNONYM INCLUDE DSK1.3RD4TH INCLUDE DSK1.MALLOC INCLUDE DSK1.VDPMEM INCLUDE DSK1.FASTCASE INCLUDE DSK1.ASMLABELS INCLUDE DSK1.GRAFIX INCLUDE DSK1.DIRSPRIT INCLUDE DSK1.COOLSPRITE
  12. How much of the 64K ROM space does Stevie use. Asking for a friend... (that's an enviable code space)
  13. I updated the code above to remove the HOLDER buffer and just used PAD. Then I realized if you wanted to, the compiler could just put the bytes directly into VDP RAM in the pattern table. You just replace C, with VC, Then you just need a word to set the VDP memory pointer to the correct location in the pattern table for the character you want to change. This code does that. So no CPU RAM is used to hold the patterns. The downside of course is that the patterns have to be re-compiled each time you want them. But I see this as simple way to design patterns on real iron.
  14. I was doing some folder housekeeping and found something I tried to do a long time ago. I guess I have learned something over the last few years because it was clear to me that it was all wrong. The objective was to make a character pattern compiler the lets you "draw" your character patterns in text in your source code like these examples. CREATE BIG-O \ 01234567 | **** | | * * | | * * | | * * | | * * | | * * | | * * | | **** | CREATE SQUARE \ 01234567 | ********| | ********| | ********| | ********| | ********| | ********| | ********| | ********| The better idea was to convert a string of asterisks and spaces into a string of ones and zeros. A string of ones and zeros can be "evaluated" by Forth as a binary number. That number can then be compiled into memory as one byte of a pattern definition. It's not nearly as fancy as a program that let's you draw on the screen but its a heck of lot easier than HEX bytes in a string. Here is the code with the examples above. Code Edit: Removed HOLDER buffer and used PAD instead. Saves bytes
  15. I am confused. (No shock there) Are we talking about file "pipes"? Pipelining to me is a technique in CPU design where you make an instruction pipeline so you can minimize stalling the CPU. If we are talking about pipes then as you say MSDOS later versions had pipes without multi-tasking. I am not certain of the exact mechanism used. (Temporary files as output/input buffers?) This sounds like something I should add to the Fox Shell with some filter programs. hmm... 🤔 with multi-tasking too.
  16. Could you get/put a low resistance shunt somewhere and compute the current?
  17. So I did a benchmark program in two versions. One that lives in completely in CPU RAM. The 2nd has the outer loop in SAMS F9 but the inner loop is in SAMS F8. This forces a cross SAMS page call. Here is the code. The screen shots tell the tale. Pages were toggling... Speed is VERY good.
  18. I have something that seems useful now although some code that I have in my libraries breaks when loaded in SAMS. Need to understand why. This version runs faster because MAPPER is now smart and does not map in a SAMS page if it is already in memory. I will do a benchmark comparison between CPU RAM and SAMS memory. Here is the code Here is a test suite using a SAMS wordlist to hold a the SAMS version of : and ; plus all the SAMS words. COMPILE-2-SAMS.mp4
  19. Maybe that's the trap that could be installed in this new BASIC interpreter. GOTO inside a FOR/NEXT structure throws an error. ?? We have to start reigning-in the bad habits of BASIC programmers somehow. :) (It's a joke. Don't kill me)
  20. "Bug for bug compatibility"
  21. You could use the EQU to reference the string address but you need a BSS with a label somewhere with the string in it. And for a string you can also use I think. TEXT 'DSK1.1234567890'
  22. When I regained consciousness... I found that I finally had a working version of FAR: / ;FAR That reduced the overhead in the Dictionary. Using the original Turbo Forth method translated to Camel99 Forth this empty definition: FAR: TEST ;FAR Took 26 dictionary bytes and 4 SAMS bytes With the work I did this week, the same definition consumes 16 Dictionary bytes and 4 SAMS bytes. I did this by making a proper colon definition for FAR: that has it's own run-time code. This replaces all the "compiled" words in the TF code and it should be faster as well. I use two data fields: Bank# and SAMS dictionary pointer. The code word FARCOL uses the IP register to read these sequential bytes into their appropriate places. It's still not giving me as much efficiency as I would like but it reduces the Forth dictionary consumption by about 40% when I load my ANS Files library. I have tested the calling overhead yet. Bugs: 1. There is a SAMS memory bug somewhere because I cannot squeeze as many files into a 4K block as I can with more direct translation of TF version that I did earlier. ?? I think I am advancing an extra cell after each definition. More sleuthing needed... 2. Changing Banks is not reliable yet. This has been way harder than I wanted it to be but thanks to Mark paving the way I had a place to begin. Here is the current state of the code: Now if you want to load existing code need to alias FAR: ;FAR to : /; The easiest way is to use a vocabulary I think. I have not tried this but it should work. VOCABULARY SAMS ONLY FORTH ALSO SAMS DEFINITIONS \ rename normal : ; so we don't over-ride them and can still use them : H: : ; : ;H POSTPONE ; ; IMMEDIATE H: : FAR: ;H H: ; ;FAR ;H IMMEDIATE There are other ways to this that don't need vocabularies. Adding vocabulary/wordlists to my system uses 550ish valuable bytes.
  23. Don't know if this is of any value but I did something with SAMS that is pretty simple but effective. It comes from a function in Forth called BLOCK. Normally BLOCK is used for files that work as virtual memory. BLOCK takes a numerical argument from 0 to >FF It returns the CPU address of a buffer, where a block of a file is loaded, but in this case it is a 4K SAMS page that is mapped into the space. I used all of the low RAM for two 4K buffers. If the SAMS page is already in memory, nothing happens. If the page is not in memory it is pulled into the last used buffer. I only have the code in reverse polish assembler. Happy to share it but you can probably make it better yourself for your purposes. It doesn't get much simpler but it lets you grab any page anytime.
  24. It would be great to have him hanging around here again. BTW I may have discovered why Mark used a separate stack for his SAMS pages. I think you need that default page# on the bottom that he has. More experiments needed.
  25. Been there going to real iron. My condolences.
  • Create New...