+TheBF Posted December 27, 2019 Author Share Posted December 27, 2019 (edited) So with the RKEY fixed the TINYED program works much better albeit with minimal features. It loads the file into VDP "screens". You then edit page by page like a Forth block editor. With this restriction and the 40 column limit it makes for rather "squished" source code which I am not a big fan of it. However the editor can edit itself with a few lines to spare. ( TINYED 9k file size, 40 cols BJF 2019 ) NEEDS DUMP FROM DSK1.TOOLS NEEDS CASE FROM DSK1.CASE NEEDS RKEY FROM DSK1.RKEY NEEDS -TRAILING FROM DSK1.TRAILING NEEDS FAM FROM DSK1.ANSFILES HEX 1F CONSTANT ULINE 1E CONSTANT BOX : GREEN 1C 7 VWTR ; : LTGRN 13 7 VWTR ; : CYAN 17 7 VWTR ; : CLIP ROT MIN MAX ; : BETWEEN ( n lo hi -- ?) 1+ WITHIN ; : ALPHA? ( -- ?) BL [CHAR] ~ BETWEEN ; : UPDT ( -- addr) VTOP @ 3FE + ; : TOUCH ( -- ) TRUE UPDT V! ; : VIRGIN ( -- ) FALSE UPDT V! ; \ variables ... VARIABLE INSERTING VARIABLE TOPLINE VARIABLE OFFSET VARIABLE SCR : GETXY ( -- col row) VROW 2@ ; CREATE FORTHXY 0 , 0 , CREATE EDITXY 0 , 0 , CREATE FILENAME 10 ALLOT DECIMAL : CUP VROW @ 0 > IF VROW 1-! ELSE HONK THEN ; : CDOWN VROW @ 23 < IF VROW 1+! ELSE HONK THEN ; : CRIGHT VCOL @ 39 < IF VCOL 1+! ELSE HONK THEN ; : CLEFT VCOL @ 0 > IF VCOL 1-! ELSE HONK THEN ; : NEWLINE ( ) CDOWN VCOL OFF ; DECIMAL : INS/DEL ( ) \ toggle mode INSERTING DUP @ -1 XOR SWAP ! INSERTING @ IF BOX CURS ! ELSE ULINE CURS ! THEN ; HEX \ vdp BLOCK creation 400 CONSTANT 1K : VBLOCK ( n -- vaddr) 4 + 1K * ; : TOUCHED? ( scr# -- ?) VBLOCK 3FE + V@ ; : ]LINE ( ndx -- addr) C/L@ * SCR @ VBLOCK + ; \ return vdp address of current row : VLINE ( -- VDPaddr) VROW @ ]LINE ; \ select VDP screen to DISPLAY : ACTIVE ( scr# -- ) 4 + 2 VWTR ; : SCRCOLOR ( -- ) SCR @ TOUCHED? IF LTGRN ELSE GREEN THEN ; : SCREEN ( n --) 0 9 CLIP SCR ! 0 ]LINE VTOP ! SCR @ ACTIVE SCRCOLOR ; : RIGHTSIDE ( -- VDPaddr len) VLINE C/L@ VCOL @ /STRING ; : LEFTSIDE ( -- VDPaddr len) VLINE VCOL @ 1+ ; \ copy vdp string to RAM address : VCOPY ( vaddr len addr --) SWAP VREAD ; \ text manipulation : DELCHAR ( -- ) RIGHTSIDE 1 /STRING TUCK PAD VCOPY PAD VPOS ROT VWRITE ; : PUSHRIGHT ( -- ) RIGHTSIDE TUCK PAD VCOPY BL VPUT PAD VPOS 1+ ROT 1- VWRITE ; HEX : FORTH ( -- ) \ goto forth console 0 02 VWTR VTOP OFF CYAN GETXY EDITXY 2! FORTHXY 2@ AT-XY ULINE CURS ! ABORT ; HEX : PURGE ( -- ) 09 0 DO I VBLOCK 1K BL VFILL VIRGIN LOOP 9 VBLOCK C/SCR @ BL VFILL VIRGIN SCR OFF ; VARIABLE HNDL : OPEN ( adr len fam -- ) OPEN-FILE ?FILERR HNDL ! ; : CLOSE HNDL @ CLOSE-FILE HNDL OFF ?FILERR ; : READ ( addr len -- addr len') HNDL @ READ-LINE ?FILERR DROP ; : WRITE ( addr len -- ) HNDL @ WRITE-LINE ; HEX : LOADSCR ( -- eof) 0 L/SCR 0 DO HNDL @ EOF IF DROP TRUE LEAVE ELSE PAD DUP 50 READ I ]LINE SWAP VWRITE THEN LOOP ; : LOADFILE ( addr len --) PURGE DV80 R/O OPEN SCR OFF BEGIN LOADSCR ( -- ?) SCR 1+! UNTIL CLOSE ; : SAVESCR ( n -- ) SCR ! L/SCR 0 DO I ]LINE C/L@ PAD VCOPY PAD C/L@ -TRAILING WRITE IF FORTH ." Write error" THEN LOOP ; : SAVEFILE ( addr len --) DV80 R/W OPEN 0A 0 DO I TOUCHED? IF I SAVESCR THEN LOOP CLOSE SCR OFF ; : TINK ( -- ) 80 SND! 2 SND! 92 SND! 25 MS 9F SND! ; : PGDWN ( ) SCR @ DUP 0 = IF DROP HONK ELSE 1- SCREEN TINK THEN ; : PGUP ( ) SCR @ DUP 9 = IF DROP HONK ELSE 1+ SCREEN TINK THEN ; HEX : KEYHANDLER ( char -- ) CASE 02 OF PGDWN ENDOF 03 OF DELCHAR ENDOF 04 OF INS/DEL ENDOF 0C OF PGUP ENDOF 0D OF NEWLINE ENDOF 08 OF CLEFT ENDOF 0B OF CUP ENDOF 0A OF CDOWN ENDOF 09 OF CRIGHT ENDOF 90 OF VIRGIN PAGE ENDOF 93 OF TOUCH ENDOF 95 OF VCOL OFF ENDOF 96 OF C/L@ 1- VCOL ! ENDOF 0F OF FORTH ENDOF HONK ( unknown key) ENDCASE ; DECIMAL : EDIT ( scr# -- ) DUP 0 9 BETWEEN INVERT ABORT" Bad screen#" SCR ! VMODE @ 2 <> IF TEXT THEN GETXY FORTHXY 2! INSERTING OFF ULINE CURS ! SCR @ SCREEN 0 0 AT-XY BEGIN RKEY DUP ALPHA? IF INSERTING @ IF PUSHRIGHT THEN VPUT CRIGHT TOUCH ELSE KEYHANDLER THEN SCRCOLOR AGAIN ; TINYED.mp4 Edited December 27, 2019 by TheBF Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4418668 Share on other sites More sharing options...
+TheBF Posted December 28, 2019 Author Share Posted December 28, 2019 On 11/29/2019 at 11:47 AM, TheBF said: CAMEL99 Forth V2.5 Release ### Known BUG - When INCLUDE is used for a file on a disk other than DSK1, the library files will try to load from that same disk. Investigating our FILESYSX for the problem. - Temporary fix is to keep programs on disk one or load libraries manually before loading a program from DSK2 or DSK3. DSK1.zip 109.09 kB · 5 downloads This was not a bug in Camel99 Forth. It was my wrong setup of Classic99 causing DSK3 to be replaced by DSK1. So this is resolved. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4419084 Share on other sites More sharing options...
+TheBF Posted December 29, 2019 Author Share Posted December 29, 2019 Some people can write very elegant Forth code. Found this greatest common denominator on Rosetta Code. Way outta my league. : gcd ( a b -- n ) begin dup while tuck mod repeat drop ; Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4419645 Share on other sites More sharing options...
+TheBF Posted December 30, 2019 Author Share Posted December 30, 2019 One of things I remember fondly about programming DOS was the multiple screens that you could use in the graphics memory. Now that I have figured out how to do this on the TI-99 I am going to change the CAMEL99 kernel to provide this feature while remaining backwards compatible if you only use the default display screen. I have added a new variable called VPG (vdp page). This variable contains the offset into VDP RAM where the screen resides, simply a multiple of >400. The VPG variable is used to calculate VDP screen addr with col & row and provides a block offset into VDP RAM for that calculation. A new word has been added called TOPLN, which returns the VDP address of the top line on the screen, calculated by adding the variables VPG+VTOP. Setting VTOP to something other than zero allows you to create a protected portion of the screen at the top that will not be cleared by PAGE. For now I have decided that this is enough "windowing" for my requirements and so I don't have a VEND variable in the system. The SCREEN allows the use of any 1K boundary to be used as the display memory to allow flexibility in different modes. So in the code below SCREEN 1,2 and 3 cannot be used because the patterns descriptor table etc. are located there. If you move these things around SCREEN will let you set the display memory where you want it. So the library file to provide names screens becomes: \ Multiple named screens in 32 or 40 Column mode HEX : SCREEN ( n -- ) 400 * VPG ! ; : SCREEN: ( scr# fg bg -- ) SWAP 4 LSHIFT + \ colors to byte CREATE ( color) , ( scr#) , 400 VP +! \ allocate 1K vdp ram DOES> 2@ 7 VWTR \ set color DUP SCREEN 2 VWTR ; \ Vpage fg bg \ ----- -- -- 0 1 7 SCREEN: SCR0 4 1 3 SCREEN: SCR4 5 1 4 SCREEN: SCR5 I will be beating this up and will get the code up on Github early in the new year. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4420694 Share on other sites More sharing options...
+TheBF Posted January 2, 2020 Author Share Posted January 2, 2020 I have been seeing what could be done to improve my lack-lustre scroll routine without resorting to writing it all in Assembler. I took a Forthy approach and did one with no loops. Turns out it is not much faster that what I had before but it was good to see the limits of what could be done. The new one is a little quicker than before and by using a feature of the cross compiler I removed the text labels of the MOVUP and the CHUNK word from the EA5 program image so that saves a few bytes. I am using a 4 line buffer controlled by CHUNK. I don't think I can get it faster without using all assembler. The speed is about 48mS with a 4 line buffer and it only drops to ~46mS with a buffer the size of the screen. I also made use of inlining kernel words to make CHUNK faster. I haven't changed the cross-compiler for over a year so it's pretty stable. [PRIVATE] CODE: CHUNK ( -- n) CODE[ C/L@ 4* ] NEXT, END-CODE : MOVEUP ( vaddr -- 'vaddr) H @ OVER C/L@ + ( -- 1stline heap 2ndline) OVER CHUNK VREAD OVER CHUNK VWRITE CHUNK + ; [PUBLIC] : SCROLL ( -- ) \ 4.58 / 100 scrolls TOPLN MOVEUP MOVEUP MOVEUP MOVEUP MOVEUP MOVEUP DROP 0 17 CLRLN ; 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4422447 Share on other sites More sharing options...
+TheBF Posted January 2, 2020 Author Share Posted January 2, 2020 (edited) After the scroll exercise I wondered if there was anything I could do with VREAD and VWRITE. How about move 2 bytes at a time and loop 1/2 as many times? Turns out it seems to work. It improved the scroll time from 47mS to 40mS, a 17% improvement. I divide the loop counter and then align it to an even value. It costs 20 bytes. I think I will make the counter massaging into a sub-routine to save a few bytes. EDIT: Unfortunately I am seeing errors in some graphics programs unsurprisingly. I may just try an assembler scroll version that uses these concepts. CODE: VREAD ( VDP-adr RAM-addr cnt -- ) R1 POP, \ pop buffer addr. to R1 R0 POP, \ pop VDP addr. to R0 R3 VDPRD LI, \ put the VDP read port address in R3. 12.9% faster RMODE @@ BL, \ call the RMODE control routine TOS 1 SRA, \ divide count by 2 TOS INCT, TOS -2 ANDI, \ align to even address boundary BEGIN, *R3 *R1+ MOVB, \ READ char from VDP RAM into CPU RAM , autoINC *R3 *R1+ MOVB, \ READ 2nd char TOS DEC, \ dec the counter EQ UNTIL, \ jump back if carry flag not set TOS POP, \ refill TOS NEXT, END-CODE CODE: VWRITE ( RAM-addr VDP-addr cnt -- ) R0 POP, \ vaddr to R0 R1 POP, \ cpu addr to R1 TOS TOS MOV, \ protect from cnt=0 like CMOVE NE IF, WMODE @@ BL, R3 VDPWD LI, \ vdp addr. in a reg. makes this 12.9% faster TOS 1 SRA, \ divide count by 2 TOS INCT, TOS -2 ANDI, \ align to even address boundary BEGIN, *R1+ *R3 MOVB, \ write byte to vdp write port *R1+ *R3 MOVB, \ write 2nd byte TOS DEC, \ dec the byte counter EQ UNTIL, \ jump back if no carry flag set ENDIF, TOS POP, NEXT, END-CODE Edited January 2, 2020 by TheBF bugs bugs bugs 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4422453 Share on other sites More sharing options...
+TheBF Posted January 4, 2020 Author Share Posted January 4, 2020 (edited) I had always wondered if I could make a progress bar for the TI-99. Turns out it was a little more code than I expected but this works. I couldn't think of a simple way to compute the values of left to right vertical lines in a character so I make a lookup table. The algorithm uses 2 characters. One character is a solid block and the second is invisible. With a numeric input we use /MOD to compute the number of complete blocks to draw and we use the modulo result to select the correct number of vertical lines to add to the invisible character. To use it you put word PROGRESS in the loop with the x,y position and it will update. You erase it with NEWBAR. This version has no way to calibrate to a specific width but that would be a good enhancement. I could envision it doing a wrap when a limit was encountered. It is not too big if you don't try to overgeneralize it (like you would in OOP) to use in a TI-99 application. And... I found another use for my new primitive 1+@. EDIT: Updated with final code that restores cursor position after progress bar is moved. *Demo changed to "TESTS". Takes input argument for defined number of tests \ Progress BAR for Camel99 Forth bfox Jan 5, 2020 NEEDS HCHAR FROM DSK1.GRAFIX HEX FFFF FFFF FFFF FFFF PATTERN: ABLOCK ABLOCK 0 CHARDEF \ char 0 is the block : FILLCHAR ( HEXpat ascii -- ) ]PDT 8 ROT VFILL ; : GET-XY ( -- x y ) VROW 2@ ; \ define vertical line pattern from left to right CREATE LNVALUES 00 C, 80 C, C0 C, E0 C, F0 C, F8 C, FC C, FE C, \ input value fills Character 1 with correct pattern : HFINE ( 0..7 -- 'c ) LNVALUES + C@ 1 FILLCHAR ; : HGRAPH ( n -- ) 8 /MOD ?DUP IF DUP VPOS SWAP 0 VFILL VCOL +! THEN HFINE 1 EMIT ; \ ===[ User API words ]=== VARIABLE BARY : PROGRESS ( x y -- ) GET-XY 2SWAP AT-XY BARY 1+@ HGRAPH AT-XY ; : NEWBAR ( x y -- ) GET-XY 2SWAP CLRLN BARY OFF AT-XY ; : BARCOLOR ( n -- ) 0 SWAP 1 COLOR ; \ DEMO DECIMAL : TESTS ( n -- ) 7 BARCOLOR 0 ?DO 0 0 NEWBAR 237 0 DO 0 0 PROGRESS 25 MS LOOP LOOP ; PROGRESSBAR.mp4 Edited January 5, 2020 by TheBF Final code 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4424485 Share on other sites More sharing options...
+TheBF Posted January 5, 2020 Author Share Posted January 5, 2020 (edited) Two speedups for the VDP Driver After I changed WITHIN to use the stack items in memory rather than popping them into registers I wondered if there were any other places I could do that. Turns out my VC! (VSBW in TI speak) could be improved significantly: \ VSBW Forth style pronounced "Vee-Cee-store" CODE: VC! ( char Vaddr -- ) TOS R0 MOV, WMODE @@ BL, *SP SWPB, *SP+ VDPWD @@ MOV, \ write char & POP TOS POP, \ refill TOS NEXT, END-CODE I may have committed a serious faux pas here but note the use of the MOV instruction to write a byte to the VDP write data port. This allows me to write the data and POP the Forth Data stack at the same time. It seems to work. Let me know why I can't/shouldn't do it. I don't think there is anything for the extra byte to write to but I have been wrong many times. The second speedup is regarding trying to speed VREAD/VWRITE (VMBR/VMBW) by writing 2 bytes in the inner loop. I tried changing both which resulted in a resounding CRASH. However when I only changed VREAD it worked. This is probably because all my strings are aligned to even addresses when they are created. \ VMBR Forth style CODE: VREAD ( VDP-adr RAM-addr cnt -- ) R1 POP, \ pop buffer addr. to R1 R0 POP, \ pop VDP addr. to R0 R3 VDPRD LI, \ put the VDP read port address in R3. 12.9% faster RMODE @@ BL, \ call the RMODE control routine TOS INCT, TOS -2 ANDI, \ align to even address boundary BEGIN, *R3 *R1+ MOVB, \ READ char from VDP RAM into CPU RAM , autoINC *R3 *R1+ MOVB, \ READ 2nd char TOS DECT, \ dec the counter by 2 EQ UNTIL, \ jump back if carry flag not set TOS POP, \ refill TOS NEXT, END-CODE The bottom line is that with these two changes the SEVENS7 problem test speeds up by 4.5% because of faster scrolling and text typing. That's a pretty good improvement. Edited January 5, 2020 by TheBF typo 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425277 Share on other sites More sharing options...
+Lee Stewart Posted January 5, 2020 Share Posted January 5, 2020 (edited) 3 hours ago, TheBF said: I may have committed a serious faux pas here but note the use of the MOV instruction to write a byte to the VDP write data port. This allows me to write the data and POP the Forth Data stack at the same time. It seems to work. Let me know why I can't/shouldn't do it. I don't think there is anything for the extra byte to write to but I have been wrong many times. All of the VDP windows start on even addresses and, because only 1 byte is passed through each of those windows, it would appear safe to do what you did. ? 3 hours ago, TheBF said: The second speedup is regarding trying to speed VREAD/VWRITE (VMBR/VMBW) by writing 2 bytes in the inner loop. I tried changing both which resulted in a resounding CRASH. However when I only changed VREAD it worked. This is probably because all my strings are aligned to even addresses when they are created. The write to VRAM probably takes longer to recover than the read, although I thought @Tursi had determined that, in practice, we could not outrun the VDP. If that is, indeed, what is happening, why not try a NOP, (see edit below) between the writes to see whether that is faster than a single-write loop? [EDIT: I do not know how you would implement NOP, in Camel99 Forth. It is not defined in fbForth, so it would need to be replaced with “ 0 JMP, ” there.] ...lee Edited January 5, 2020 by Lee Stewart correction of NOP, Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425329 Share on other sites More sharing options...
+TheBF Posted January 6, 2020 Author Share Posted January 6, 2020 4 hours ago, Lee Stewart said: All of the VDP windows start on even addresses and, because only 1 byte is passed through each of those windows, it would appear safe to do what you did. ? The write to VRAM probably takes longer to recover than the read, although I thought @Tursi had determined that, in practice, we could not outrun the VDP. If that is, indeed, what is happening, why not try a NOP, (see edit below) between the writes to see whether that is faster than a single-write loop? [EDIT: I do not know how you would implement NOP, in Camel99 Forth. It is not defined in fbForth, so it would need to be replaced with “ 0 JMP, ” there.] ...lee That's an interesting idea. I have NOP in the Assembler which I took from TI-Forth as a starting place. : NOP, ( -- ) 0 JMP, ; I will give it a try, but I think it's failing because I am writing to the wrong place with that extra byte in some cases. The first thing that fails is opening the DSK1.START file. So that is the PAB read/write process. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425487 Share on other sites More sharing options...
+Lee Stewart Posted January 6, 2020 Share Posted January 6, 2020 35 minutes ago, TheBF said: I have NOP in the Assembler which I took from TI-Forth as a starting place. : NOP, ( -- ) 0 JMP, ; I do not think it was in the original TI Forth Assembler or I would have it in fbForth’s. Someone must have added it to the copy from which you got it. ...lee Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425518 Share on other sites More sharing options...
+TheBF Posted January 6, 2020 Author Share Posted January 6, 2020 18 minutes ago, Lee Stewart said: I do not think it was in the original TI Forth Assembler or I would have it in fbForth’s. Someone must have added it to the copy from which you got it. ...lee Lol. Maybe it was me. I might have found it in a book I bought in the 80s from TI about programming on the 990. It was only 35 years ago or so. I always loved how easy it was to make macros as colon definitions. 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425539 Share on other sites More sharing options...
+TheBF Posted January 6, 2020 Author Share Posted January 6, 2020 Found it. "Software Development" 1981 Texas Instruments, page 8-103 8.12.7 Psuedo-Instructions Instruction Format Effect ----------------------------------------------- No Operation NOP JMP $+2 Return RT B *R11 =========================================================== And to that list I have added these to the cross compiler Assembler: : IP++ IP INCT, ; : RP++ RP INCT, ; : RP-- RP DECT, ; : SP++ SP INCT, ; : SP-- SP DECT, ; \ PUSH & POP on both stacks : PUSH, ( src -- ) SP DECT, *SP MOV, ; : POP, ( dst -- ) *SP+ SWAP MOV, ; : RPUSH, ( src -- ) RP DECT, *RP MOV, ; : RPOP, ( dst -- ) *RP+ SWAP MOV, ; Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425947 Share on other sites More sharing options...
+TheBF Posted January 6, 2020 Author Share Posted January 6, 2020 (edited) VDP read/write one more time. The code below seems to work with double byte VDP read/write and half the looping. I was concerned about weird effects with strings so I compiled my experimental version of Oregon Trail. It is 995 lines long and puts 4K of text into VDP RAM. I seems to work perfectly. And with these three changes (VC!, VREAD, VWRITE) the Sevens Problem runs in 1:08 versus 1:26 with the old code. If these don't demonstrate bugs over the next while they look like real improvements. More testing required. \ VMBR Forth style CODE: VREAD ( VDP-adr RAM-addr cnt -- ) R1 POP, \ pop buffer addr. to R1 R0 POP, \ pop VDP addr. to R0 R3 VDPRD LI, \ put the VDP read port address in R3. 12.9% faster RMODE @@ BL, \ call the RMODE control routine TOS INCT, TOS -2 ANDI, \ align to even address boundary BEGIN, *R3 *R1+ MOVB, \ READ char from VDP RAM into CPU RAM , autoINC *R3 *R1+ MOVB, \ READ 2nd char TOS DECT, \ dec the counter EQ UNTIL, \ jump back if carry flag not set TOS POP, \ refill TOS NEXT, END-CODE \ =================================================================== CR ." V D P W R I T E" \ VMBW in Forth style CODE: VWRITE ( RAM-addr VDP-addr cnt -- ) R0 POP, \ vaddr to R0 R1 POP, \ cpu addr to R1 TOS INCT, TOS -2 ANDI, \ align to even address boundary NE IF, \ protect from 0 count WMODE @@ BL, R3 VDPWD LI, \ vdp addr. in a reg. makes this 12.9% faster BEGIN, *R1+ *R3 MOVB, \ write byte to vdp write port *R1+ *R3 MOVB, \ write byte to vdp write port TOS DECT, \ dec the byte counter EQ UNTIL, \ jump back if no carry flag set ENDIF, TOS POP, NEXT, END-CODE Edited January 7, 2020 by TheBF changed 8K to 4K. (>2000->1000= 4K 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4425994 Share on other sites More sharing options...
+Lee Stewart Posted January 6, 2020 Share Posted January 6, 2020 3 hours ago, TheBF said: Found it. "Software Development" 1981 Texas Instruments, page 8-103 8.12.7 Psuedo-Instructions Instruction Format Effect ----------------------------------------------- No Operation NOP JMP $+2 Return RT B *R11 =========================================================== That does not count. That is pure Assembler, not Forth Assembler. I was just saying that if it had been coded in the TI Forth Assembler blocks, I would have put it in fbForth’s FBLOCKS. I just never needed it until my suggestion for a VDP delay. You probably did what you are very good at: created it when you needed it, wanted it or thought it would be a good idea. I so enjoy watching you create Forth code. I think I am much better at reworking or finding flaws in existing code than dreaming up original code. ...lee Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426107 Share on other sites More sharing options...
+Lee Stewart Posted January 6, 2020 Share Posted January 6, 2020 2 hours ago, TheBF said: VDP read/write one more time. So, what was wrong with your original VWRITE code? ...lee Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426109 Share on other sites More sharing options...
+TheBF Posted January 7, 2020 Author Share Posted January 7, 2020 1 hour ago, Lee Stewart said: That does not count. That is pure Assembler, not Forth Assembler. I was just saying that if it had been coded in the TI Forth Assembler blocks, I would have put it in fbForth’s FBLOCKS. I just never needed it until my suggestion for a VDP delay. You probably did what you are very good at: created it when you needed it, wanted it or thought it would be a good idea. I so enjoy watching you create Forth code. I think I am much better at reworking or finding flaws in existing code than dreaming up original code. ...lee You are totally right, I believe after seeing this information I added it to the Forth Assembler. I had no idea why I would need it at the time I'm sure. Well thank you. I have always been a hybrid creature. In my youth I wanted to be a musician and did become a part-time professional musician. (it helped pay for school) I spent some time in an advertising agency and a broadcasting facility engineering department where there were opportunities for creative projects because not everything we needed could be purchased off the shelf in those days. Once I learned Forth I "created" a few projects for myself. I enjoy hanging with creative people. It pushes you. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426186 Share on other sites More sharing options...
+TheBF Posted January 7, 2020 Author Share Posted January 7, 2020 1 hour ago, Lee Stewart said: So, what was wrong with your original VWRITE code? ...lee I did not evaluate why it failed, I just tried a number of different ways to accomplish the same thing and this one worked so I migrated it back to the VREAD word. We shall see if it's really going to fly. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426188 Share on other sites More sharing options...
+TheBF Posted January 7, 2020 Author Share Posted January 7, 2020 I think I have got to the end of my improvements on my VDP driver. The last weakness was my calculation of the VDP screen address derived from the cursor row and column. So I used some of the last free bytes in the 8K image and added: CODE: GET-XY ( -- col row ) TOS PUSH, TOS STWP, 34 (TOS) PUSH, \ vcol user variable 32 (TOS) TOS MOV, \ vrow user variable NEXT, END-CODE GET-XY feeds into CODE: >VPOS ( col row -- vaddr) \ compute video address R1 STWP, TOS R3 MOV, \ this move to make best use of MPY 2E (R1) R3 MPY, \ multiply by chars/line. result goes to R4 ie: TOS *SP+ TOS ADD, \ add col value to TOS VPG @@ TOS ADD, \ add Video page offset NEXT, END-CODE Which allows the new faster VC! (VSBW) to put a character onto the correct video memory page like this \ primitive to put char on screen at cursor position : VPUT ( char -- ) GET-XY >VPOS VC! ; With all Assembly language words doing the job and the new faster scroll, which uses the faster VREAD and VWRITE, runs the Lee Stewart version of the Sevens problem in 1:10 (stop watched timing) Versus an earlier kernel of CAMEL99 that I thought was pretty fast which runs the same code in 1:26. That's almost a 23% improvement. It could be made faster by making all the routines inline, but that exceeds the memory I have left and is of questionable value since I have a direct to VDP ram word VTYPE. So far I have not seen any strange artifacts as a result of moving 2 bytes at a time in and out of VDP RAM. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426272 Share on other sites More sharing options...
+TheBF Posted January 7, 2020 Author Share Posted January 7, 2020 I was wrong It was even better to do this. It took the time down to 1:06.8 And uses less word names so it even saved space. GET-XY is simple to define later if I really need it. This way of interleaving code words only works for indirect thread code. The CFA! compiler directive takes a label and stores it in the 'code-field-address' of a word. Later when Forth "interprets" this it jumps to the address of the label. There are few superfluous instructions to make everything stack compatible, but it's not bad. variable: VPG \ holds address of VDP page ( >400 increments only) CODE: VPUT ( char -- ) \ put a char at cursor position TOS PUSH, R1 STWP, 32 (R1) R3 MOV, \ vrow->r1 2E (R1) R3 MPY, \ vrow*c/l->tos 34 (R1) TOS ADD, \ add vcol VPG @@ TOS ADD, \ add video page l: _VC! ( char Vaddr -- ) \ VSBW in Forth style pronounced "Vee-Cee-store" TOS R0 MOV, WMODE @@ BL, *SP SWPB, *SP+ VDPWD @@ MOV, \ write char & POP TOS POP, \ refill TOS NEXT, END-CODE CODE: VC! _VC! CFA! END-CODE 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4426319 Share on other sites More sharing options...
+TheBF Posted January 8, 2020 Author Share Posted January 8, 2020 BENCHIE Re-visited With V2.58 running I pulled out this old chestnut. This is the original BENCHIE that uses VALUES. In the past I had a glaring error in my implementation of the Forth word 'TO' that assigns a number to a VALUE. I was computing the address AND I was adding the 2 byte offset at runtime. Pretty stupid. The new DSK1.VALUES library file does that calculation at compile time and then compiles the computed address as a literal number into your code. This makes BENCHIE much faster. From 1:18 to 1:01. For reference Turbo Forth does this BENCHIE in 55 seconds. (stopwatch timing for all) So CAMEL99 V2.58 is only 10% off of Turbo Forth which is pretty good considering how many intrinsics are in scratch-pad RAM with Turbo Forth. Full disclosure Camel99 Forth has three primitive operations in 16 bit RAM, '@' 'DROP' and 'LIT' as well as the inner interpreter routines (enter,exit,next) and the virtual machine branching routines, ?BRANCH and BRANCH. Here is the new 'TO' in ANS Forth. It is a state smart word which is considered sinful in 2020 by the commercial Forth system writers but it works for me. : VALUE CONSTANT ; : TO ( n -- ) STATE @ IF ' >BODY \ compute PFA at compile time POSTPONE LITERAL POSTPONE ! ELSE ' >BODY ! THEN ; IMMEDIATE Here is BENCHIE as tested. \ benchie \ 8051 ANS Forth (12 MHz 80C535): 15.8 sec (with user variables) \ CAMEL99 V2.0 1:18 \ V2.58 1:01 \ TurboForth V1.2.1 0:55 INCLUDE DSK1.VALUES ( for CAMEL99 only) HEX 5 CONSTANT FIVE 100 CONSTANT MASK 0 VALUE BVAR : BENCHIE 256 0 DO 1 BEGIN DUP SWAP DUP ROT DROP 1 AND IF FIVE + ELSE 1- THEN TO BVAR BVAR DUP MASK AND UNTIL DROP LOOP ; 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4427535 Share on other sites More sharing options...
+TheBF Posted January 8, 2020 Author Share Posted January 8, 2020 Remember when we were all envious of people who had a C64? :) I went looking for Forth benchmark programs and found this site: https://theultimatebenchmark.org/ I tried this one that exercises integer calculations: DECIMAL 32000 CONSTANT INTMAX VARIABLE INTRESULT : DOINT 1 DUP INTRESULT DUP >R ! BEGIN DUP INTMAX < WHILE DUP NEGATE R@ +! 1+ DUP R@ +! 1+ R@ @ OVER * R@ ! 1+ R@ @ OVER / R@ ! 1+ REPEAT R> DROP DROP ; On CAMEL99 Forth it ran in 14.8 seconds. The reported time for an equivalent Forth system is 526 seconds. !!! And on a sub-routine threaded C64 system which should be about (more or less) the same speed as Small C, it took 37 seconds. The old girl looks pretty good. 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4427780 Share on other sites More sharing options...
+Lee Stewart Posted January 8, 2020 Share Posted January 8, 2020 5 hours ago, TheBF said: Here is the new 'TO' in ANS Forth. It is a state smart word which is considered sinful in 2020 by the commercial Forth system writers but it works for me. : VALUE CONSTANT ; : TO ( n -- ) STATE @ IF ' >BODY \ compute PFA at compile time POSTPONE LITERAL POSTPONE ! ELSE ' >BODY ! THEN ; IMMEDIATE Why not this?: : TO ( n -- ) ' >BODY \ compute PFA at compile/run time STATE @ IF POSTPONE LITERAL POSTPONE ! \ defer to runtime ELSE ! THEN ; IMMEDIATE ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4427789 Share on other sites More sharing options...
+TheBF Posted January 9, 2020 Author Share Posted January 9, 2020 27 minutes ago, Lee Stewart said: Why not this?: : TO ( n -- ) ' >BODY \ compute PFA at compile/run time STATE @ IF POSTPONE LITERAL POSTPONE ! \ defer to runtime ELSE ! THEN ; IMMEDIATE ...lee Umm... because... well ermmm... :) Nice one. 1 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4427810 Share on other sites More sharing options...
+TheBF Posted January 9, 2020 Author Share Posted January 9, 2020 First VWRITE BUG After a number of distractions I got back to looking at my ED99 editor. I encountered a bug when I tried to write a pattern to character >1F, an ODD number. I am trying a fix that is a bit of brute force, but it seems to work. I test the byte count to see if it is ODD. If so I run a single byte loop, otherwise I run a double byte loop. It solved the problem but it added a few bytes. We shall see if everything behaves. CODE: VWRITE ( RAM-addr VDP-addr cnt -- ) R0 POP, \ vaddr to R0 R1 POP, \ cpu addr to R1 TOS TOS MOV, \ 0 byte-count protection NE IF, WMODE @@ BL, R3 VDPWD LI, \ vdp addr. in a reg. makes this 12.9% faster TOS W MOV, W 0001 ANDI, \ test for odd byte count NE IF, \ ODD BYTE COUNT BEGIN, *R1+ *R3 MOVB, \ write byte to vdp write port TOS DEC, \ dec the byte counter EQ UNTIL, \ jump back if no carry flag set ELSE, \ EVEN BYTE COUNT BEGIN, *R1+ *R3 MOVB, \ write byte to vdp write port *R1+ *R3 MOVB, \ write byte to vdp write port TOS DECT, \ dec the byte counter EQ UNTIL, \ jump back if no carry flag set ENDIF, ENDIF, TOS POP, NEXT, END-CODE Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/19/#findComment-4428583 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.