Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by TheBF

  1. I was thinking that the TI world needs training videos too. Hmmm.... BF
  2. I feel your pain. LOL. You have way more patience than I do. Something to consider is that there might be enough reduction in instruction count with the wrap method ​and using workspace registers, that the speed-up matches the benefit of being in 8300 memory space. PAD memory is faster but running 2x as many instructions, with variables in slow ram, could end up being the same. Maybe someone with more experience could weigh in on this. It is possible to test some code fragments in Forth pretty quickly test for speed. BF
  3. Also, if your Interrupt routine uses it's own workspace, you don't need to keep variables since you can use the local registers to hold the queue pointers, no? (which are just memory that the machine can get at easier anyway ie: faster variables) It would be even faster again. *-------------------------------------------------------- * RS232 Circular Buffer using binary wrap method ​* no jumps required * example register usage * R3 tail pointer next byte to read * R4 head pointer next available input location * R5 byte counter INTWSP BSS >20 BUFFER BSS >100 256 byte buffer for example * interrupt handler for the queueing the characters MOVB R3,*R4+ stuff char into buffer, auto inc. puts you at next location ready for next interrupt ANDI R4 >00FF wrap R4 by ANDing with a mask. INC R5 inc total bytes in buffer RTWP In some applications with a big enough buffer, you can "live on the edge" and not even deal with overflow in the ISR. It just wraps around and it's up to your reader program to keep up! :-) However that only works if the data comes in bursts. (Or the reader program hits the handshake line to stop the sending until it catches up) BF And of course reading characters out becomes faster as well with the wrap mask method.
  4. Good point. It's an artistic effect. BF
  5. I did a lot of work with RS 232 interrupt handlers on the PC and I found it really sped things up to set the buffer size to a power of 2 and let the pointer wrap by ANDing it with a mask. It worked well in both Assembler and was very effective in Turbo C. I don't understand you code well, but I edited it without testing to show what I mean. BF
  6. I am truly a heretic. I calculate if the results will be off screen before doing anything to the screen. I know that's not like BASIC but it is way faster. ?EOSCR ABORTs with a message if the TOS is greater than the last VDP address for the mode.
  7. I had not looked at TI BASIC since 1987 ish.. I forgot that it could do more than 1 vertical column. I have repented of my evil ways. But it's not a very valuable feature is it? (oops once a heretic...) BF
  8. After sleeping on it an alternative algorithm might be to read the entire screen into a buffer. VCHAR into the buffer and write buffer back to VDP RAM. This might be faster for big values and slower for small ones. (?) Needs to be tested BF
  9. When I looked at it I thought it was pretty optimal as well. Here are some timings that I did today to get a Forth version to run a little faster. First a reference in BASIC 10 CALL CLEAR 20 FOR C=33 TO 83 30 CALL VCHAR(1,1,C,768) 40 NEXT C 50 REM runtime: 63 secs Forth Version of the 50 iteration test ran on Turbo Forth in 5.5 secs. : TEST PAGE 83 33 DO 0 0 I 768 VCHAR LOOP ; My first version Forth version of VCHAR based on the Turbo Forth algorithm is below and it ran "TEST" in 23 seconds. 2.5x BASIC speed but 1/4 of TF speed. VARIABLE T : VCHAR ( x y char cnt -- ) ( parameter order not ideal so we shuffle) C/SCR @ 1- VLIM ! ( chars / screen less 1 goes to VLIM) >R >R ( -- x y ) ( push char & cnt to rstack) >VPOS ( -- vdpaddr) ( calc the Video position in memory) R> SWAP ( -- char vadr) ( get the char and reverse order) R> 0 ( -- char vadr cnt index) ( all that crap to get this) ?DO ( -- char vadr) ( let 'er rip) 2DUP VC! ( write char to video memory) C/[email protected] + DUP T @ > IF T @ - THEN LOOP 2DROP ; Then I wrote the VWRAP to do the increment and compare the variable in ASM so the final version looks like this and that runs in 13 seconds so 2.4x slower than TF but 4.8 times faster than BASIC. I also like the idea of telling the programmer they have put in too many bytes. I cannot think of a reason why VCHAR needs to accept 32K bytes for a little screen. I suppose if it wrote pixels it would make sense, but it's way to slow for that. : VCHAR ( x y char cnt -- ) ( parameter order not ideal so we shuffle) DUP ?EOSCR C/SCR @ 1- VLIM ! ( chars / screen less 1 goes to VLIM) >R >R ( -- x y ) ( push char & cnt to rstack) >VPOS ( -- vdpaddr) ( calc the Video position in memory) R> SWAP ( -- char vadr) ( get the char and reverse order) R> 0 ( -- char vadr cnt index) ( all that crap to get this) ?DO ( -- char vadr) ( let 'er rip) 2DUP VC! ( write char to video memory) VWRAP ( This 5 instruction word doubles the speed) LOOP 2DROP ; *EDIT* It sucks when your humanity shows. Apr 13 I had an error in all these VCHARs that caused them to write one line less than they should have so these times are light by 4%. But the magnitudes are in the right order.
  10. lol. Well I am old enough to know that I know very little. So I will continue listening. By the way, for some reason I missed the fact that VCHAR and HCHAR could accept 32k character count until I read the BASIC manual again. duh! So I went back to the bible (TurboForth) to look at the ASM method. You pointed out that in FBForth you re-wrote these things in ASM because they were so slow. My HCHAR is fast because it uses VMBW. My new VCHAR in Forth is about 1/3 the speed of Turbo Forth which is not a bad number for a Forth vs pure ASM comparison. I had to resort to a gratuitous variable. I will think it over more. But this is an interesting example where stack juggling items 3 deep is a pain in the butt. I could get to 1/2 speed of ASM probably by hand coding the LIMIT check inside the loop. More... ( C/L is characters per line) ​( L/SCR is lines per screen ) : >VPOS ( col row -- VPOS) C/[email protected] * + ; ( calc VDP address from col & row) VARIABLE T : VCHAR ( col row char cnt -- ) ( parameter order not ideal so we shuffle) 0 L/SCR 1- >VPOS 1- T ! ( calc. the 1st screen limit) >R >R ( -- x y ) ( push char & cnt to rstack) >VPOS ( -- vdpaddr) ( calc the Video position in memory) R> SWAP ( -- char vadr) ( get the char and reverse order) R> 0 ( -- char vadr cnt index) ( all that crap to get this) ?DO ( -- char vadr) ( let 'er rip) 2DUP VC! ( write char to video memory) C/L+ DUP T @ > ( check for end of screen) IF T @ - THEN LOOP 2DROP ; BF
  11. Wow that is a lot of overhead for a random number. I will look into how you do it in a "system compatible" way. ​Thanks for the continued schooling Lee BF
  12. To get VCHAR to go faster without writing everything in Assembler I did this to my original version. This pretty much doubled the speed. Turns our the ?EOSCR test that uses ABORT" was very slow to put inside a loop. ( created this little word to speed up C/L @ +) CODE: C/L+ ( n -- n') _C/L @@ TOS ADD, NEXT, END-CODE : VCHAR ( x y char cnt -- ) >R >R >VPOS R> SWAP R> 0 ?DO 2DUP VC! C/L+ ( use tiny ASM word inside the loop) C/SCR @ MIN ( *EDIT* clipping the value is faster) LOOP 2DROP ;
  13. I have been amazed at the level of BASIC programs people are generating here for TI-99. I spent many hours a few decades ago (ya that sounds weird to me too) inside XB myself. To continue my torture I decided to add TI-BASIC style GRAPHIC words to CAMEL99. Out of curiosity I wrote a program with the new additions and then duplicated it in TI-BASIC. I was amazed at how with these higher level functions the two programs lined up. However I did have make a quick and dirty random number generator. Raw Forth like Assembler is pretty low level. But that's the game with it. Raise the level. I have some 10 second videos but they need converting and it's late. I will do it another day. (*EDIT* VIDEO IS ATTACHED) By the way, the color set numbers are correct because Forth accesses 32 color sets provided by the VDP chip so char 131 is in it's color set 16. ( Graphics test program ) VARIABLE RND# HEX : SCRAMBLE ( -- n) 83D6 @ 8379 [email protected] * C3E9 XOR ; ( we had to build a random number generator) : RANDOMIZE ( -- ) SCRAMBLE RND# ! ; ( named it like TI-BASIC ) : RND ( n -- ) ( this one too ) RND# @ SCRAMBLE XOR >< ABS DUP RND# ! SWAP MOD ; DECIMAL : RND(X) ( -- x) 23 RND 1+ ; ( no sense in repeating the math) : RND(Y) ( -- y) 31 RND 1+ ; ( when it is so easy to call it ) : RND(C) ( -- c) 15 RND 1+ ; HEX" FFFF 0000 FFFF 0000" 131 CHARDEF ( 20 CALL CHAR(159,F0F00F0FF0F00F0F") ) : STUFF ( 25 REM STUFF name of routine) BEGIN CLEAR ( 30 CALL CLEAR) ( BEGIN is like line# 30, to jump back to) RND(C) SCREEN ( 40 CALL SCREEN(INT(RND*16)+1) ) 16 RND(C) RND(C) COLOR ( 50 CALL COLOR(16,INT(RND*16)+1,INT(RND*16)+1) ) RND(Y) 0 ?DO ( 60 FOR I=1 TO INT(RND*32)+1 ) RND(Y) RND(X) 131 RND(X) VCHAR ( 70 CALL VCHAR(INT(RND*24)+1,INT(RND*32)+1,159,INT(RND*24)+1)) LOOP ( 80 NEXT I ) 20000 0 DO ( 90 FOR X=1 TO 200 ) ( yes loops are about 100x faster) LOOP ( 100 NEXT X ) KEY? ABORT" *Break" ( 105 REM FORTH loops don't have BREAK built-in) AGAIN ; ( 110 GOTO 30 ) ( actually GOTO BEGIN ) TI-BASiC CAMEL99 GRAPHICS.mov
  14. To paraphrase Churchill regarding the US and UK : "We are two programmers separated by a common language" BF
  15. I know you mean. I took a look at VCHAR and it was huge!. I reduced it to this. : ?EOSCR ( vdpadr -- ) C/SCR @ > ABORT" off screen" ; : VCHAR ( x y char cnt -- ) ( parameter order not ideal so we shuffle) >R >R ( -- x y ) ( push char & cnt to rstack) >VPOS ( -- vdpaddr) ( calc the Video position in memory) R> SWAP ( -- char vadr) ( get the char and reverse order) R> 0 ( -- char vadr cnt index) ( all that crap to get this) ?DO ( -- char vadr) ( let 'er rip) 2DUP VC! ( write char to video memory) C/L @ + ( calc. next row) DUP ?EOSCR ( did we go too far?) LOOP 2DROP ; Maybe my top of stack cache and few other speed-ups will keep it moving. But for sure the stack juggling to get parameters in order is painful My actual goal is education on how to cross-compile Forth so I shouldn't be so concerned but... Hi level Forth still performs better than BASIC right? BF *edit* As I look at this I think it can go faster if I use the loop index to calculate the VDP address directly.
  16. Thanks Lee, Here are the definitions in ANS Forth. Not fancy as you can see, and they do a hard switch back to decimal. ( HEX" converts a string into HEX numbers and returns to DECIMAL radix) : HEX" ( -- <text>) HEX [CHAR] " PARSE EVALUATE DECIMAL ; ( BIN" converts a binary number string onto the stack returns to DECIMAL radix) : BIN" ( -- <text>) 2 BASE ! [CHAR] " PARSE EVALUATE DECIMAL ; Well if it helps I am liberally "borrowing" graphics code from TI-Forth. Found some quick gains in the words that use 4 * and 8 * multiple times in the graphics BLOCKS Changed them to : : 4* ( n -- n.4) 2 LSHIFT ; : 8* ( n -- n. 3 LSHIFT ; I think these are about 4X faster than using 4 * because of the Forth NEXT linkage and save a few bytes too, being re-used. Part of the reason for the TI-BASIC color scheme is to assist any daring TI-BASIC programmer who might be interested in trying Forth. Things like control values get locked into your mind after working with a system for awhile, so I feel their (potential) pain. EDIT* I suppose I could add something like "OPTION BASE" that is used in BASIC. Hmmm.. BF
  17. I have been working on developing TI-BASIC style GRAPHICS for CAMEL99 Forth. My thoughts on the matter are to make these things work similar to TI-BASIC where possible. For example the color values are the same, 1 through 16, even though the hardware wants 0 to 15. I have replicated the simple things CLEAR, SCREEN, COLOR and even added a new one called COLORS which changes background and foreground colors for the entire character set in one line. Years ago something that was always a pain was developing graphics shapes for CALL CHAR. Nowadays I see there is a great editor for the job that outputs BASIC code. Very cool. The CALL CHAR sub-program tries to make it simpler for us by letting us input a hexadecimal string for the character bits and a decimal number for the ASCII value. In Forth I could switch the radix wtih HEX and DECIMAL and it would look like this: HEX FFFF FFFF FFFF FFFF DECIMAL 128 CHARDEF ( I had to call it something different because CHAR is already a standard word in ANS Forth so I chose CHARDEF) I didn't like that much so I automated the number conversion from HEX to DECIMAL by adding a word called HEX" HEX" FFFF FFFF FFFF FFFF" 128 CHARDEF That was good enough thought I... but what if I could input the bits as BINARY numbers? So I created BIN" And now with the help of the swap-byte operator '><' and the '+' operator I can do this: BIN" 01111110" >< ( swap this byte to other side: 00FF becomes FF00 ) BIN" 10000001" + ( add this byte to the previous one to create a 16bit number) BIN" 10100101" >< BIN" 10000001" + BIN" 10100101" >< BIN" 10011001" + BIN" 10000001" >< BIN" 01111110" + 128 CHARDEF It's not as nice as a real icon editor but sure is faster for me to code than using HEX numbers. BF
  18. An item on my bucket list was to write a cross-compiler that created a Forth system for our venerable TI-99. Here is the state of my work so far: https://github.com/bfox9900/CAMEL99 There is a runnable program file called CAMEL99. It's not finished, but it shows one way to create a Forth system from another Forth system in case you ever wondered. The source files for the cross-compiler framework and the cross-assembler are in the COMPILER folder. (I know it's a pretty short list of people on the planet who care, but I was one them) If you have any questions just post them here. BF
  19. This sounds like a cool thing Speccery. What tool chain are you using for VHDL. I have a Papillio board here with a Spartan 6 on it but have never got around to getting a working toolchain. BF
  20. 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
  21. You are correct again. I had never tested it. B
  22. Changes necessary for fbForth 2.0: Removed ALIGNED (not sure what it is doing there because alignment screws up loop in NTH—no alignment necessary until next definition, which aligns itself ...lee I put aligned in the string definition to cope with odd length strings. You have challenged my assumptions to the core. Thanks! BF
  23. I stole the Nth concept from HsForth and it required a 0 leading and a 0 ending the lists. Never bothered to change it. So creating the [[ ]] just made some syntax candy. Ending the list with 0 means Nth can't go past the end of the list. My lists don't work correctly if I remove the leading 0 byte... hmmm... By the way although Bruce is a very good name, mine is Brian. :-) BF But I was a big Bruce Lee fan!
  • Create New...