+TheBF Posted November 20, 2019 Author Share Posted November 20, 2019 (edited) The question becomes how long will it take to find text using SEARCH. I wrote a test suite (by re-purposing the MORE utility, that loads a text file into an 8K buffer as contiguous text Then using the elapsed timer I sent SEARCH looking for one of the last words in the buffer. (at byte 5669) The screen shot shows the timing. Spoiler has the test code. Not really speedy but not bad for the old TI-99 using a brute force algorithm. \ TEST SEARCH IN A LARGE BUFFER INCLUDE DSK1.TOOLS INCLUDE DSK1.ELAPSE NEEDS SEARCH FROM DSK1.SEARCH NEEDS OPEN-FILE FROM DSK1.ANSFILES NEEDS VALUES FROM DSK1.VALUES 0 VALUE LINEBUFF CREATE FILEBUFF 2000 ALLOT \ buffer management VARIABLE BP : FALLOT BP +! ; : FHERE FILEBUFF BP @ + ; : FILEBUFF$! ( addr n -- ) TUCK FHERE SWAP CMOVE FALLOT ; : BUFFC, ( c -- ) FHERE C! 1 FALLOT ; : FBSIZE ( -- n ) FHERE FILEBUFF - ; 1A CONSTANT ^Z DECIMAL : LOADFILE ( <filename>) 80 MALLOC TO LINEBUFF BL PARSE-WORD DUP ?FILE DV80 R/O OPEN-FILE ?FILERR >R BEGIN LINEBUFF DUP 50 R@ READ-LINE ?FILERR ( -- addr n ?) WHILE \ 2DUP CR TYPE FILEBUFF$! ." ." ?TERMINAL IF R> CLOSE-FILE 2DROP CR ." HALTED" ABORT THEN REPEAT R> CLOSE-FILE ^Z BUFFC, \ ^Z at the end of the text 2DROP DROP 80 MFREE CR FBSIZE . ." bytes in buffer" ; DECIMAL Edited November 20, 2019 by TheBF Fixed spoiler 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395694 Share on other sites More sharing options...
+Lee Stewart Posted November 20, 2019 Share Posted November 20, 2019 5 hours ago, TheBF said: I have library file for COMPARE IN Forth, that is code published by a late pioneer of Forth named Neil Baud (also know by the pseudonym Wil Baden) That is a very clever use of COUNT ! I do not believe I ever would have thought of using it that way. I also do not usually think of using EXIT in the middle of a definition in that manner, but I will be keeping it in mind in the future. Of course, if I want to use it in the middle of a DO loop in fbForth, I will need to define UNLOOP , which I presume is : UNLOOP R> R> DROP DROP ; ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395720 Share on other sites More sharing options...
+TheBF Posted November 20, 2019 Author Share Posted November 20, 2019 9 minutes ago, Lee Stewart said: That is a very clever use of COUNT ! I do not believe I ever would have thought of using it that way. I also do not usually think of using EXIT in the middle of a definition in that manner, but I will be keeping it in mind in the future. Of course, if I want to use it in the middle of a DO loop in fbForth, I will need to define UNLOOP , which I presume is : UNLOOP R> R> DROP DROP ; ...lee Ya Neil was some smart cookie. I noticed that too. I would probably never had used COUNT but would have made a new word that did the same thing. I beleive he was involved in some kind of text analysis of books and wrote his own tools. You can see his style here: http://www.wilbaden.com/neil_bawd/ I have only recently started to realize the EXIT and factoring can allow a modest form of "un-structuring" in Forth programs (as I did with (SRCH) allowing us to branch out of a loop and land inside another word. Some might call it cheating. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395733 Share on other sites More sharing options...
+Lee Stewart Posted November 21, 2019 Share Posted November 21, 2019 13 minutes ago, TheBF said: I have only recently started to realize the EXIT and factoring can allow a modest form of "un-structuring" in Forth programs (as I did with (SRCH) allowing us to branch out of a loop and land inside another word. Some might call it cheating. I do not see why. You are not actually branching into the middle of a word, you are terminating the current word early and landing where you would have with a normal completion, anyway. Maybe it is not intuitively obvious to the casual observer, but I certainly would not even think of calling it cheating. ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395741 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 (edited) Not that you really need it but I made unloop in CODE and it is part of my DO LOOP system, but can be called separately as well. I waffled on the big version or the smaller 1 instruction version. CODE: UNLOOP RP 4 ADDI, ( *RP+ *RP+ CMP,) NEXT, END-CODE Edited November 21, 2019 by TheBF Added the word You. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395745 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 16 minutes ago, Lee Stewart said: I do not see why. You are not actually branching into the middle of a word, you are terminating the current word early and landing where you would have with a normal completion, anyway. Maybe it is not intuitively obvious to the casual observer, but I certainly would not even think of calling it cheating. ...lee By using a separate word and EXITing it is like I jumped over 1 /STRING and the REPEAT word which puts me back inside SEARCH. I have not built these "quotations" that I read about in comp.lang.forth but I believe they would allow me to do what I did without putting the word (SRCH) in the dictionary. Something like this: HEX : SEARCH ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag ) 100 DUP >R MALLOC TO SBUFF [: SBUFF PLACE ( QUOTATION starts here) BEGIN DUP WHILE SBUFF COUNT 2OVER SAMELEN COMPARE 0= IF EXIT THEN \ NOW EXIT jumps to ;] 1 /STRING REPEAT ;] DUP 0> R> MFREE 0 TO SBUFF ; Here it is clearer to see that I am doing a GOTO I may have to try and create these quotation things... 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395749 Share on other sites More sharing options...
+Lee Stewart Posted November 21, 2019 Share Posted November 21, 2019 11 minutes ago, TheBF said: Not that really need it but I made unloop in CODE and it is part of my DO LOOP system, but can be called separately as well. I waffled on the big version or the smaller 1 instruction version. The ADDI, is definitely faster than CMP, by 16 clock cycles and 3 memory accesses! What was your more-than-1-instruction version? ...lee Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395750 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 Just now, Lee Stewart said: The ADDI, is definitely faster than CMP, by 16 clock cycles and 3 memory accesses! What was your more-than-1-instruction version? ...lee I mis-spoke, I should have said 2 CELLs vs 1 CELL version. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395751 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 Just to round off the discussion of quotations, I found this document and I think the code is very possible for Camel Forth. http://www.forth200x.org/quotations.txt Implementation -------------- It is not possible to define quotations in ISO Forth. The following is an outline definition, where SAVE-DEFINITION-STATE and RESTORE- DEFINITION-STATE require carnal knowledge of the system and are left to the implementor. : [: ( c: -- quotation-sys colon-sys ) postpone ahead save-definition-state :noname ; immediate : ;] ( c: quotation-sys colon-sys -- ) ( s: -- xt ) postpone ; >r restore-definition-state postpone then r> postpone literal ; immediate Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395757 Share on other sites More sharing options...
+Lee Stewart Posted November 21, 2019 Share Posted November 21, 2019 OK, that makes my head hurt a little. I guess that construct somehow compiles what is within [: ... ;] as a word with no header such that the effect is the same as before, but saving the 10 bytes for a header in the process. ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395762 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 2 minutes ago, Lee Stewart said: OK, that makes my head hurt a little. I guess that construct somehow compiles what is within [: ... ;] as a word with no header such that the effect is the same as before, but saving the 10 bytes for a header in the process. ...lee Exactly. And if you read the paper they talk about dealing RECURSE and DOES> and that makes my head hurt. I would just make those two illegal along with ;CODE Topic Shift I was just looking at Neil's page after a long time away and found this: \ The traditional definition for (.) is: \ : (.) ( n -- str len ) \ dup ABS 0 <# #S ROT SIGN #> ; \ But we like to see TRUE and SIGN-BIT in hex as FFFFFFFF and \ 80000000, and also see bit masks as unsigned. It would be nice to \ let the program do it. \ : (.) ( n -- str len ) \ BASE @ 10 = IF dup ABS ELSE 0 SWAP THEN \ 0 <# #S ROT SIGN #> ; \ Even nicer would be the following. This helps in distinguishing \ similar binary numbers. Like 0FFFFFFF from FFFFFFFF and 08000000 \ from 80000000. : (.) ( n -- str len ) CASE BASE @ 10 OF dup ABS 0 <# #S ROT SIGN #> ENDOF 16 OF 0 <# BEGIN # # 2dup OR 0= UNTIL #> ENDOF 2 OF 0 <# BEGIN # # # # 2dup OR 0= UNTIL #> ENDOF 0 <# #S #> 0 ENDCASE ; \ Of course we want with whichever one... : . ( n -- ) (.) TYPE SPACE ; I think I am going to add the big version to my programmers tools file with .S and DUMP and the like. I hate seeing signed HEX numbers and having to use U. all the time to print them when debugging stuff. He also uses this to define .S 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4395764 Share on other sites More sharing options...
+TheBF Posted November 21, 2019 Author Share Posted November 21, 2019 (edited) After seeing the VDP I/O performance of FbForth in the sevens problem topic I decided to dig in on what I could do to improve text writing speeds while at the same time keeping the hi-level code in Forth for instructional purposes. I had a faster scroll in place but that was only part of the issue. The Forth word TYPE was written in Forth and although the word that wrote to the VDP memory (VC!) was Assembler, Forth was used to update the column variable, detect the end of screen and then to call SCROLL. I wanted to see how much things could move faster if I improved TYPE but I didn't want to re-write everything in Assembler because it probably would take more space and my 8K limit was looming. How about removing setting up the address for each character and leverage the VDP hardware's auto-increment capability? I gave Forth direct access to the set the VDPWA which disables interrupts and is a callable routine in the kernel. Then the mate to it is VEMIT which writes a character, increments the VCOL variable and returns the new VCOL. New Assembler routines: Note on STWP below. System (USER) variables are located below the workspace so that each task can have its own copy. No. $34 is VCOL (video column) variable \ *NEW* For faster TYPE routine in Forth CODE: VDPWA! ( Vaddr -- ) TOS R0 MOV, WMODE @@ BL, TOS POP, NEXT, END-CODE \ VEMIT writes to VDP address set by VDPWA! and updates VCOL user variable \ VDP auto increments the address for faster character output CODE: VEMIT ( char -- column') TOS SWPB, TOS VDPWD @@ MOVB, \ write char to vdp data port R1 STWP, 34 (R1) INC, \ Bump VCOL user variable 34 (R1) TOS MOV, \ fetch VCOL to TOS NEXT, END-CODE By returning the VCOL value it can be passed to the conditional newline routine called ?CR. If VCOL >= chars-per-line , ?CR calls the newline routine CR. CR resets VCOL and increments VROW. If VROW >= lines-per-screen it calls SCROLL. With all this in place the new faster TYPE routine reduces to: : CR ( -- ) PAUSE VCOL OFF VROW 1+! VROW @ L/SCR 1- > IF SCROLL THEN ; : ?CR ( column -- ) C/L@ 1- > IF CR THEN ; : TYPE ( adr cnt -- ) VPOS VDPWA! BOUNDS ?DO I C@ VEMIT ?CR LOOP ; Using Lee's version of the Seven's Problem the slowest combination of SCROLL and TYPE ran in 1:25 on Camel99 Forth. (FbForth time is: 0:53 seconds using the ELAPSE timer) Using the fast scroll and and fast type the program ran in 1:06. That's a 29% improvement. I still have 50 bytes left in the kernel for an emergency change so V2.54 is going to be the current system. I can't beat an I/O driver written with integrated Assembler scroll and newline but I got much closer. Edit: I also had to add one line to SCROLL to set the VDPWA to the bottom line to make this all work. Edited November 21, 2019 by TheBF 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4396293 Share on other sites More sharing options...
+TheBF Posted November 24, 2019 Author Share Posted November 24, 2019 It was all fun and games trying to make a faster VDP I/O system for the sevens problem, but I forgot one little detail... CAMEL99 Forth is supposed to Support multi-tasking. So if you set the VDP write address, write a character and then change tasks and that new task does some screen I/O guess what happens? Now I could control for that but forcing screen typing to hog the system until it completes everything including newlines and screen scrolls but that makes other tasks "lumpy" in the way they run so I have reverted. For a cooperative Forth tasker it's best that the fundamental I/O operation does a task switch so in this case I have a low level (EMIT) word that does the job. It also shaved 42 bytes out the system by not having the faster TYPE routine. I can live with it. I did find one thing that makes a speedup and that is a word I call '1+@' It increments a variable and fetches the new value in one word. This makes screen variable management for row and column quite a bite faster as the fastest way to do it in Forth is: \ Standard Forth options 1 VCOL +! VCOL @ VCOL 1 OVER +! @ \ Versus VCOL 1+@ Time to watch the Grey Cup, Canadian football final game. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4397891 Share on other sites More sharing options...
+TheBF Posted November 29, 2019 Author Share Posted November 29, 2019 (edited) CAMEL99 Forth V2.5 Release I am a poor administrator but I have finally committed to one version of the kernel program CAMEL99. It seems pretty stable now but I am the only one who has used it. Attached is a ZIPped up version of DSK1. to make it simple to try it out. The biggest difference between CAMEL99 and the other TI-99 Forths out there is the that CAMEL99 attempts to be ANS/ISO compliant. Not a big deal for hobby coding but there it is. If you want to try it mount the DSK1 in the ZIP file to Classic99, use Editor/Assembler cartridge and select E/A 5. Program name is DSK1.CAMEL99. "COLD" <enter> restarts the system. Try INCLUDE DSK1.COOLSPRITE to compile a demo program with libraries. (It takes 36 seconds to compile the approximately 480 lines of code at normal speed) Type RUN to make it go. BREAK will stop it. Type BYE to exit. A slightly updated version of the instruction manual (mostly typo corrections) will be up there some time later today. I realize Forth doesn't win popularity contests but if anybody wants to try it I am happy to answer any and all questions. ### Nov 28, 2019 V2.5 Indirect Threaded Version - Settled on one build of CAMEL99 Forth. All variations are removed. - 25% speed up of CREATE DOES> structures by using BRANCH & LINK instruction - Fixed DSK1.ANSFILES file handle bug. Errors did not release current file handle. - Improved VDP screen driver using 1+@ code word - Improved DSK1.VALUES. Faster TO and +TO - Cleaned up LIB.ITC. TI99 versions are in DSK1. - Added DSK1.TRAILING. (-TRAILING -LEADING TRIM) - Added DSK1.HEXNUMBER. H# is a prefix word to interpret numbers as radix 16. - DSK1.TOOLS now includes VDUMP for VDP ram and SDUMP code for SAMS card. (HEX and BINARY numbers alway print unsigned after tools are loaded.) - DSK1.CODEMACROS provides native 9900 indexed addressing arrays. - DSK1.VTYPE improved VTYPE updates VCOL. AT" ( x,y) placing text. - DSK1.AUTOMOTION provides Automatic sprite motion like Extended BASIC ### 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 Edited December 7, 2019 by TheBF No bug when loading from DSK2. Not tested on hardware 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4400630 Share on other sites More sharing options...
+TheBF Posted December 1, 2019 Author Share Posted December 1, 2019 I am reviewing, running and editing, when necessary, all the DEMO programs on GITHUB. https://github.com/bfox9900/CAMEL99-V2/tree/master/DEMO It looks like V2.5 is a better multi-tasking kernel. I was able to run 43 total tasks. (42+console) This consumes almost the entire lower 8k for the task blocks. Version 2.x Would only do 30 tasks and then it would blow up. Each task is just running this: HEX 10 CONSTANT STKSIZE VARIABLE X \ used to test if tasks are running : DROPS ( n --) 0 DO DROP PAUSE LOOP ; \ drop items from the stack : STKTHING \ fill and clear data stack so it can be seen in debugger BEGIN STKSIZE 0 DO PAUSE DEAD LOOP STKSIZE DROPS STKSIZE 0 DO PAUSE BEEF LOOP STKSIZE DROPS 1 X +! AGAIN ; 43TASKSONTHECAMEL.mp4 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4401934 Share on other sites More sharing options...
+TheBF Posted December 3, 2019 Author Share Posted December 3, 2019 On the outside chance that anyone cares... there is an updated version of the Manual for CAMEL99 Forth. https://github.com/bfox9900/CAMEL99-V2/blob/master/DOCS/Camel99 for TI-BASIC Programmers Rev1.9.pdf Or if you would rather something smaller, there is a list of the library files with one liner of what they do. (Extracted from the Manual) https://github.com/bfox9900/CAMEL99-V2/blob/master/DOCS/Camel99 Forth Library files.pdf The most complete list of lib files in TI-99 format will always be here: https://github.com/bfox9900/CAMEL99-V2/tree/master/DSK1.ITC Some font files are here: https://github.com/bfox9900/CAMEL99-V2/tree/master/DSK3 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4402680 Share on other sites More sharing options...
+TheBF Posted December 4, 2019 Author Share Posted December 4, 2019 So here is something that I don't understand. (A common motif) I went looking for a bug that I found just recently where I try to load a file on DSK3. The file on DSK3. begins to load, but the file has "nested" statements that say INCLUDE DSK1.FILE#1, INCLUDE DSK1.FILE#2 etc Even though the statements specify DSK1 for the extra includes, the system goes looking for FILE#1 and FILE#2 on DSK3. Hmm... However when I put the identical file on DSK2. it begins to load and loads the nested includes from DSK1. as the statements in the file request. The screen shot shows what I am trying to describe. You can see the failure including DSK3.SAMSDEMO at the top. Next I load DSK2.SAMSDEMO and it moves through the 5 lib files on DSK1 first before completing the load on DSK2. Is there something different about DSK3 that makes it unique compared to DSK1 and DSK2 ? Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4403427 Share on other sites More sharing options...
+TheBF Posted December 9, 2019 Author Share Posted December 9, 2019 (edited) What da' ya' mean you want another stack? Forth already has two stacks. Why would you ever need another one? Well a stack is a handy data structure. I am working on a demonstration of the shunting yard algorithm to convert infix math to rpn. For that I need to keep a stack for the brackets and operators. I looked at some code from my very old HsForth system and modified it for Camel99 Forth. I have not tried it on other TI-99 Forth systems but it should not be too hard to adapt. You might need to add these definitions: : 2@ ( adr -- n1 n2 ) DUP 2+ @ SWAP @ ; : CELL+ ( n -- n') 2+ ; The word to create the data structure here is called LIFO: ( last in first out) which is a fancy name for a stack. You might prefer the word stack. LIFO: creates 3 integer locations to manage the stack. The PUSH and POP words have built in error detection which can save your bacon in a real program. Spoiler removed until bugs are killed... Edited December 9, 2019 by TheBF 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4407198 Share on other sites More sharing options...
+Lee Stewart Posted December 9, 2019 Share Posted December 9, 2019 2 hours ago, TheBF said: The word to create the data structure here is called LIFO: ( last in first out) which is a fancy name for a stack. You might prefer the word stack. LIFO: creates 3 integer locations to manage the stack. The PUSH and POP words have built in error detection which can save your bacon in a real program. 2-! looks like a victim of cut-n-paste. It should read : 2-! ( addr -- ) DUP @ 2- SWAP ! ; A couple of other items: I think the comments for the first two items are confusing. The stored numbers are the number of bytes rather than the number of cells. Does the stack pointer slot have a future purpose not obvious from the current code? I definitely like the idea of a protected stack. Very nice! ...lee Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4407318 Share on other sites More sharing options...
+TheBF Posted December 9, 2019 Author Share Posted December 9, 2019 There are some big bugs here I made it work for for my other project and was happy to have a user stack. Sincere apologies. I will work it over. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4407382 Share on other sites More sharing options...
+Lee Stewart Posted December 9, 2019 Share Posted December 9, 2019 2 hours ago, TheBF said: There are some big bugs here I made it work for for my other project and was happy to have a user stack. Sincere apologies. I will work it over. Don’t mind me! Certainly no apologies are necessary. I was, mayhap, a bit too quick on the uptake. Part of this is just my wish to insure that we avoid confusing the host of passersby! ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4407514 Share on other sites More sharing options...
+TheBF Posted December 10, 2019 Author Share Posted December 10, 2019 23 hours ago, Lee Stewart said: 2-! looks like a victim of cut-n-paste. It should read : 2-! ( addr -- ) DUP @ 2- SWAP ! ; A couple of other items: I think the comments for the first two items are confusing. The stored numbers are the number of bytes rather than the number of cells. Does the stack pointer slot have a future purpose not obvious from the current code? I definitely like the idea of a protected stack. Very nice! ...lee Fixed the bug with 2-!. It was the real culprit. Thanks. I fixed the comment changing cells to bytes. I went back into the archives of old HsForth files, circa 1990ish, and discovered that the comment I used for the stack pointer was only in my re-write and that in fact it looks like Jim added an extra cell with a zero in it for unknown reasons. Perhaps it is a safety zone? 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4408116 Share on other sites More sharing options...
+TheBF Posted December 11, 2019 Author Share Posted December 11, 2019 (edited) Searching Faster I revisited my search code and I had needlessly complicate my conversion of the S= ("string equals") code routine in Camel Forth to the ANS standard word COMPARE. I then improved the definition of 2OVER by using "4TH" a little routine borrowed from Neil Bauds toolbox that picks the 4th stack item and pushes onto the top of the stack. Due to the 9900 instruction set this Forth command is the same speed as OVER. So "4TH 4TH" makes a very fast 2OVER word. For maximum speed I rolled these up as text macros. Arguably they should be state smart but since they will be embedded in an editor I am going to leave them as is. Bottom Line: This version does the same search of DSK1.ASM9900 in 4.48 seconds vs 7 seconds. \ search.fth Forth 2012 word \ INCLUDE DSK1.TOOLS NEEDS VALUE FROM DSK1.VALUES NEEDS 3RD FROM DSK1.3RD4TH \ S= is CAMEL Forth primitive : COMPARE ( a1 n1 a2 n2 -- -1|0|1 ) S" ROT MIN S=" EVALUATE ; IMMEDIATE : 2OVER ( d d2 -- d d2 d) S" 4TH 4TH" EVALUATE ; IMMEDIATE 0 VALUE SBUFF \ temp buffer for search string : (SRCH) ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3) SBUFF PLACE BEGIN DUP WHILE SBUFF COUNT 2OVER COMPARE 0= IF EXIT THEN ( jump to ';') 1 /STRING REPEAT ; HEX : SEARCH ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag ) 100 DUP >R MALLOC TO SBUFF (SRCH) DUP 0> R> MFREE 0 TO SBUFF ; Edited December 11, 2019 by TheBF 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4408708 Share on other sites More sharing options...
+TheBF Posted December 26, 2019 Author Share Posted December 26, 2019 (edited) Using Multiple Screens in Camel99 Forth While reviewing the VDP Programmers Guide I got more familiar with the internal register functions. It seemed obvious after that, that it was possible to have different "screens" for text in the Camel Forth environment. When I implemented it I discovered a gap in my VDP driver. I had built a variable called VTOP that held the VDP address of the top line but I had assumed that the the screen always began at VDP address >0000. (oops) I had to add one instruction to my VDP address calculator routine which takes the column and row to do the computation. ( the row variable is called VROW and it is a USER variable, meaning it is based on the workspace address. That's why the 2E (R1) is used below) I just needed to add the value of VTOP as an offset into VDP RAM in the last line of code. 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 VTOP @@ TOS ADD, NEXT, END-CODE I had also made this assumption in my scroll routine ie: The end of the screen was always equal to the no. of bytes in a screen since the screen started at >0000. Mistake. So I had to fix that as well. : SCROLL ( -- ) PAUSE \ addresses on stack H @ ( -- heap) VTOP @ DUP C/L@ + ( -- heap 1stline 2ndline ) SWAP C/SCR @ + SWAP ( -- heap 2ndline lastline ) DO I ( -- heap 2ndline lastline) OVER 2DUP C/L@ VREAD SWAP C/L@ - C/L@ VWRITE C/L@ +LOOP 0 17 CLRLN DROP ; With those changes made it THEN became simple to do this: (Edit: Updating VP was wrong) \ Multiple screens in 40 Column mode HEX : SCREEN ( n -- ) 400 * VTOP ! ; : SCREEN: ( scr# fg bg -- ) SWAP 4 LSHIFT + \ combine color values to a byte CREATE ( color) , ( scr#) , 400 VP +! \ allocate 1K vdp ram DOES> 2@ 7 VWTR \ set color DUP SCREEN 2 VWTR ; \ DEMO code \ Vpage fg bg \ ----- -- -- \ 0 1 7 SCREEN: SCR0 \ 4 1 3 SCREEN: SCR4 \ 5 1 4 SCREEN: SCR5 The word SCREEN lets you choose a different screen as the destination for the VDP device driver. (EMIT TYPE CR etc.) The VDP chip takes the value of register 2 * >400 and puts text at that address. So SCREEN calculates that and stores it in VTOP. The second line just updates the VP variable which Camel99 Forth uses to keep track of how much VDP RAM is in use. The word SCREEN: lets you define words that hold the color and the screen number. When these words are executed they automatically change the screen and the color. I did not make an attempt to remember the col and row values for each screen, but this could be done. I also did not try to protect the programmer from stomping on SCREEN 1,2 or 3 which hold the pattern tables etc. in CAMEL99 Forth TEXT mode. You have been warned. The video shows the code in action. It is possible to create upto 8 extra screens but if you need 3 files open at the same time you will be limited to 7. (I think) If you choose to re-organize the VDP space you could also the control data to the top of VDP and keep the text screens contiguous. I may go there in future. I used this idea to make a 40 column editor that loads a file into VDP ram and is edited like Forth BLOCKs. Not sure it is all that practical but it works. MULTISCREEN.mp4 Edited December 26, 2019 by TheBF Changed video to MP4 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4417985 Share on other sites More sharing options...
+TheBF Posted December 27, 2019 Author Share Posted December 27, 2019 (edited) Once upon a time a guy tried to write a Forth kernel. Since he had all the source code he decided to change it... a lot. I was scratching my head about how my "totally cool" repeating key routine kept randomly plopping a random key on the screen. The method was based on code from the Tech pages but converted to Forth. How could it possibly be incorrect? ?? Turns out a few generations back I re-organized how my KSCAN interface worked. I used to read the char buffer in Forth after calling KSCAN. Somewhere in the past I decided to change that and just grab the character in Assembler if there was one to grab. However I neglected to update where I re-enabled interrupts. This made no problems until I was grabbing keys at high speed. Good news is that I found it. I will be publishing a new version very soon. I have re-organized some of the source code to try and make clearer. \ BAD VERSION CODE: KEY? ( -- ?) TOS PUSH, TOS CLR, \ TOS will be our true/false flag 0 LIMI, 83E0 LWPI, \ switch to GPL workspace 000E @@ BL, \ call ROM keyboard scanning routine 2 LIMI, \ ** ERROR WAS HERE *** WRKSP0 LWPI, \ return to Forth's workspace , interrupts are restored 837C @@ R0 MOVB, \ read GPL status byte (=2000 if key pressed) NE IF, 8374 @@ TOS MOV, \ read the key ENDIF, NEXT, \ return END-CODE \ NEW VERSION CODE: KEY? ( -- ?) TOS PUSH, TOS CLR, \ TOS will be our true/false flag 0 LIMI, 83E0 LWPI, \ switch to GPL workspace 000E @@ BL, \ call ROM keyboard scanning routine WRKSP0 LWPI, \ return to Forth's workspace 837C @@ R0 MOVB, \ read GPL status byte (=2000 if key pressed) 2 LIMI, \ ** THE FIX *** NE IF, 8374 @@ TOS MOV, \ read the key ENDIF, NEXT, \ return END-CODE Edited December 27, 2019 by TheBF fixed comment 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/18/#findComment-4418638 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.