+TheBF Posted March 31, 2018 Author Share Posted March 31, 2018 CAMEL99 Forth 'MORE' utility demonstration video using ANS Forth file words. MOREDEMO.mp4 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 1, 2018 Author Share Posted April 1, 2018 Well I am really enjoying having a working file system on Camel99 Forth. \ print string left justified : $.LEFT ( $ width -- ) OVER C@ - >R COUNT TYPE R> SPACES ; DECIMAL : ?CR OUT @ 10 + C/L@ > IF CR THEN ; HEX : DIR ( <DSK?.> ) \ needs the '.' ONLY shows file name BL PARSE-NAME DUP ?FILE RELATIVE 100 FIXED R/O BIN OPEN-FILE ?FILERR >R \ push handle onto Return stack PAD 50 R@ READ-LINE ?FILERR CR PAD COUNT TYPE CR LINES OFF BEGIN PAD 50 R@ READ-LINE ?FILERR WHILE DROP \ don't need the byte count PAD 0A $.LEFT 2 SPACES ?CR ?TERMINAL \ check for *BREAK* key IF R> CLOSE-FILE \ if detected we're done here 2DROP CR CR ." *BREAK*" ABORT THEN 1 LINES +! REPEAT R> CLOSE-FILE 2DROP 2DROP DECIMAL CR CR LINES @ . ." files" HEX ; 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 2, 2018 Author Share Posted April 2, 2018 Version 2.0.5 is On GitHub https://github.com/bfox9900/CAMEL99-V2 Found some ways to simplify the kernel and remove some names from the dictionary in FILESYSD Fixed a bug in ANSFILES.F that broke "INCLUDE". Uploaded the DIR.F and MORE.F The new STRINGS.F package is pretty fast and let's you do most of what you can do in BASIC. Todo: Add LOAD and SAVE function Create an editor Make the editor a binary overlay for rapid loading inside the system. Soon I will have to wake up my real iron, repair it and see if this all works in the real world. BF Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 7, 2018 Author Share Posted April 7, 2018 (edited) Preliminary CAMEL99 Forth Document Available https://github.com/bfox9900/CAMEL99-V2/tree/master/DOCS I have created a document to help BASIC programmers understand the things added to Forth for TI BASIC users. It has a few example programs in the text to let people see how these additions work. I feel like these are the best way to explain things. Let me know if anything doesn't make sense or is broken and I can keep working on it. The system feels pretty stable to me for what it does. I am sure some real users will find the killer bugs pretty quickly. B Edited April 7, 2018 by TheBF 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 8, 2018 Share Posted April 8, 2018 Let me know if anything doesn't make sense or is broken and I can keep working on it. B Very well-written document! I have not had a chance at low-level scrutiny (will get there later), but I like what I see. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 8, 2018 Author Share Posted April 8, 2018 Very well-written document! I have not had a chance at low-level scrutiny (will get there later), but I like what I see. ...lee Thanks I have found some errors myself already. :-) Appreciate your eagle eyes when you have the time. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 11, 2018 Author Share Posted April 11, 2018 (edited) I am writing and writing... to make something of an instruction manual for CAMEL99. I started on the Assembler and wrote this for the opening. I think it is worth sharing. Learning Assembly Language the Easy Way One of the big secrets about Forth is the Forth Assembler. It gives you a way to learn Assembly language in a way that is so much less painful than the traditional Assembler process. You can learn by writing tiny routines that do simple things but very quickly. You must still understand how the TMS9900 CPU operates and any other system details that your program uses but it follows the “How do you eat an elephant principle?” Answer: Piece by piece. Consider this traditional Assembly language work flow: 1. Write your program in the editor, save as SOURCE file 2. Assembler the program with the Assembler, giving OBJECT file. 3. *Link the OBJECT file with the LINKER giving BINARY file 4. Load the BINARY file into RAM and watch it CRASH 5. Goto 1 *TI-99 joins step 3 and 4 with a special “LINKING LOADER” program so they were aware of this issue. Now consider how you make and Assembler program in Forth” 1. Start CAMEL99 Forth 2. Load the Assembler (becomes part of Forth) 3. Write a short CODE word in Assembly language 4. Test the CODE word by typing its name A CODE Word Example Let’s imagine we wanted a way to increment a Forth variable by two at maximum speed. It turns out that the 9900 CPU can do that in one instruction. Very fast. Let’s test this idea in the Forth console. INCLUDE DSK1.TOOLS.F \ give us the programmer tools INCLUDE DSK1.ASM9900.F \ give us the Assembler words \ “two-plus-store” adds 2 to the contents in addr \ TOS is the CPU register where CAMEL99 caches the “top of stack” value CODE 2+! ( addr -- ) *TOS INCT, NEXT, ENDCODE \ test it at the Forth console VARIABLE X X ? 0 ok X 2+! X ? 2 ok X 2+! X ? 4 Seems to work. We are done! “2+!” is now just another word in the Forth dictionary but it runs really fast. Edited April 11, 2018 by TheBF 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 13, 2018 Author Share Posted April 13, 2018 Latest Edition of CAMEL99 Doc is up on GitHub Revision .5 contains a lot more material that lets you get started playing with Forth. Introduction 8 About CAMEL Forth 8 What you have 9 Library Files 9 File Format 9 Only Needs the E/A Package. 9 File Naming Convention (Optional) 9 Forth Terminology 10 Standard Forth vs CAMEL99 Forth 12 Library files Available with CAMEL99 Forth 12 The Forth Programming Pyramid 13 *Incremental Compiling 13 Loading CAMEL99 14 DSK1.START 14 Lesson 1: Jump Right in 15 Hello World 15 The Colon Compiler 16 Final Thoughts on Hello World 19 Error messages 19 Lesson 2: Transition from BASIC to Forth 20 Structured Programming 21 Moving Closer to Forth Style 21 Trim the Fat 21 Minimal 22 Factoring is the key to good Forth 22 Lesson 3: The DATA Stack 23 What is a computer stack? 23 A Few More Math Examples 25 A Fundamental Difference between BASIC and Forth 25 Why do we use a Stack? 25 EMIT 26 Stack Diagrams 27 Lesson 4: The DO LOOP 28 And one more thing… 30 If you are very curious 30 Strings in Forth 31 CAMEL99 String Word Set 31 Using CAMEL99 String Words 32 Technical Details about STRINGS.F 33 Other Facts 33 Graphics Words 34 A New Word for Convenience 36 COLOR in CAMEL99 37 Memory Tips and Tricks 38 High CPU RAM 38 Low CPU RAM 38 VDP Memory 38 SAMS Memory 38 Fetch and Store for each Space 38 Memory Operators 39 CPU RAM Memory Words 39 VDP Memory Words 39 SAMS Card Memory 39 Stealing Memory Temporarily 41 Temporary Memory Example Program 43 Multi-Tasking 44 Why Multi-Task? 44 Multi-Tasking Commands 44 TASK SWITCHER TECHNICAL EXPLANATION 46 Techie Stuff for the TMS9900 Nerd 47 WARNING for Assembly Language Users 47 CAMEL99 MULTI-TASKING USER AREA 48 Example Multi-tasking Code 49 Assembly Language the Easy Way 50 A CODE Word Example 50 Understanding Our Code Word 51 CAMEL99 Assembler vs TI Assembler 52 Forth Assembler Differences 52 Code Comparison 52 Special Registers in the Forth Machine 53 Proper Use of the TOS Register 53 Structured Branching and Looping 55 Example Programs 56 Random Color Dots 56 Guess the Number in Forth 57 GRAPHICS Example: “Denile” 58 Forth Style Version of Denile 61 Important Idea 61 Many little repairs to demonstration programs. It never ends but I have other work for today. Happy Friday the 13th 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 15, 2018 Author Share Posted April 15, 2018 (edited) Between power outages due to the ice storm I have been working to improve the speed of the CAMEL99 V2 kernel but stay within the 8K limit of the cross-compiler. It is fascinating that many times Assembler code takes more bytes to implement a simple routine that Forth. So the game is truly finding the places that make a difference. One routine that seems to perk up the system is the Forth word HERE which returns the address of the next available memory in the dictionary. It does nothing but fetch the contents of the dictionary pointer variable called DP. Since HERE is used in a lot of places in the kernel, using the extra 2 bytes it takes to code it in Assembler makes a nice improvement. \ it turns out that by making HERE faster, the system goes faster because HERE is used a lot. \ : HERE DP @ ; (Forth version) CODE: HERE ( -- addr) TOS PUSH, DP @@ TOS MOV, NEXT, END-CODE The other routine that I have benchmarked with Turbo Forth is scrolling. TF uses Assembler and also provides a lot more functionality but in normal scrolling it was much faster. I have finally got a Forth based scroll that uses a 2 line buffer that seems to scroll up at about the same speed as TF. The routine takes advantage of the Forth DATA stack to hold values for reading VDP and writing VDP. This makes it a little cryptic but it works. By changing the constant C/S you can make the line buffer bigger. In 80 col mode however I find taking 4 lines (360 bytes) a little extreme and performance does not improve much. So this is now my final scroll. [CC] C/L @ 2* [TC] CONSTANT: C/S \ chars per scroll : SCROLL ( -- ) C/S DUP \ get char per scroll and duplicate MALLOC ( -- c/s heap) \ allocate chars per scroll in heap C/SCR @ C/L@ VTOP @ + \ loops from 2nd line, to end of screen DO I ( -- c/s heap scr-addr) OVER 2DUP C/S VREAD \ read chars/scroll to heap PAUSE SWAP C/L@ - C/S VWRITE \ write HEAP to line above C/S +LOOP \ advance loop by chars per scroll 0 17 CLRLN \ clear last line DROP \ drop heap pointer MFREE ; \ de-allocate heap memory Version 2.0.8 will go up on GitHub .... if the power stays up . Edited April 15, 2018 by TheBF Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 16, 2018 Author Share Posted April 16, 2018 I found another couple of words that make a significant difference without taking more space. >DIGIT converts a small number to an ASCII digit. HOLD puts a digit into memory in a little buffer and maintains a pointer into the buffer going right to left as a number is converted digit by digit. Both of these are part of the hi level command called '#' which puts both >DIGIT and HOLD inside a loop. Because they are inside a primary loop making them faster improves performance with every iteration. Here is their Forth code : >DIGIT ( n -- c) DUP 9 > 7 AND + 30 + ; \ convert n to ascii digit c \ decr. HOLD pointer HP, Store char at the address contained in HP : HOLD ( char -- ) -1 HP +! HP @ C! ; And here are their ALC replacements CODE: HOLD ( char -- ) \ 2 BYTES bigger, 4X faster HP @@ DEC, HP @@ W MOV, TOS SWPB, TOS *W MOVB, TOS POP, NEXT, END-CODE \ : >DIGIT ( n -- c) DUP 9 > 7 AND + 30 + ; \ convert n to ascii digit c CODE: >DIGIT ( n -- c) \ ASM is 8 bytes smaller 4X faster TOS 9 CMPI, @@1 JLE, \ if n<=9 jump to convert it TOS 7 ADDI, \ else number is not base 10, add 7 @@1: TOS 30 ADDI, \ add 30 to create ASCII value NEXT, END-CODE So I save space on these two and number printing measure about 50% faster. The is new code is up on GITHUB now. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 17, 2018 Author Share Posted April 17, 2018 Between power outages due to the ice storm I have been working to improve the speed of the CAMEL99 V2 kernel but stay within the 8K limit of the cross-compiler. It is fascinating that many times Assembler code takes more bytes to implement a simple routine that Forth. So the game is truly finding the places that make a difference. One routine that seems to perk up the system is the Forth word HERE which returns the address of the next available memory in the dictionary. It does nothing but fetch the contents of the dictionary pointer variable called DP. Since HERE is used in a lot of places in the kernel, using the extra 2 bytes it takes to code it in Assembler makes a nice improvement. \ it turns out that by making HERE faster, the system goes faster because HERE is used a lot. \ : HERE DP @ ; (Forth version) CODE: HERE ( -- addr) TOS PUSH, DP @@ TOS MOV, NEXT, END-CODE The other routine that I have benchmarked with Turbo Forth is scrolling. TF uses Assembler and also provides a lot more functionality but in normal scrolling it was much faster. I have finally got a Forth based scroll that uses a 2 line buffer that seems to scroll up at about the same speed as TF. The routine takes advantage of the Forth DATA stack to hold values for reading VDP and writing VDP. This makes it a little cryptic but it works. By changing the constant C/S you can make the line buffer bigger. In 80 col mode however I find taking 4 lines (360 bytes) a little extreme and performance does not improve much. So this is now my final scroll. [CC] C/L @ 2* [TC] CONSTANT: C/S \ chars per scroll : SCROLL ( -- ) C/S DUP \ get char per scroll and duplicate MALLOC ( -- c/s heap) \ allocate chars per scroll in heap C/SCR @ C/L@ VTOP @ + \ loops from 2nd line, to end of screen DO I ( -- c/s heap scr-addr) OVER 2DUP C/S VREAD \ read chars/scroll to heap PAUSE SWAP C/L@ - C/S VWRITE \ write HEAP to line above C/S +LOOP \ advance loop by chars per scroll 0 17 CLRLN \ clear last line DROP \ drop heap pointer MFREE ; \ de-allocate heap memory Version 2.0.8 will go up on GitHub .... if the power stays up . 2 STEPS FORWARD, 1 STEP BACK DOIN' THE SOFTWARE 2 STEP... I will be publishing version 2.0.9 later today because this little gem had a bug where it killed the top 2 records of my sprite table when it scrolled in GRAPHICS mode. I tested with my PONG demo program but of course PONG does not scroll. I can't use a constant that is pre-calculated for all modes. DUH! B Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 21, 2018 Author Share Posted April 21, 2018 ANS/ISO Forth Files I am in the process of documenting the handle based file system in CAMEL99 Forth. It seems to work pretty well. The ANS Forth file words may be a little more primitive than BASIC programmers are used to so I may add a layer on top to make closer to BASIC. However it is really fun to have a handle based file system on the TI-99. The Spoiler contains the code to implement this subset of forth Files wordset. More information is here: http://forth-standard.org/standard/file CR .( ANSFILES for CAMEL99 V2 BJF 02APR2018) \ Requires CAMEL99 V2 with DISKDSR4 and FILESYSD \ A subset of ANS Forth files wordset with TI-99 specific file control words \ Dependancy: \ TI-99 file system is record oriented not byte oriented \ therefore READ-FILE and WRITE-FILE are part of this lexicon. \ ANS/ISO Forth Definitions used in this code: \ fid - file identifier (a file handle) \ ior - input/output response (the error number) \ fam - file access mode. see code for details \ primitive file sys. commands for reference \ : OPEN ( -- ior) 0 FILEOP ; \ : CLOSE ( -- ior) 1 FILEOP ; \ : READ ( -- ior) 2 FILEOP ; \ : WRITE ( -- ior) 3 FILEOP ; \ : REWIND ( -- ior) 4 FILEOP ; \ : LOAD ( -- ior) 5 FILEOP ; \ : SAVE ( -- ior) 6 FILEOP ; \ : DELETE ( -- ior) 7 FILEOP ; \ : SCRATCH ( -- ior) 8 FILEOP ; CR .( ..) \ File handle server HEX VARIABLE #FILES CREATE PABS ( -- addr) \ table for 8 potential PABs 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , \ ]PTAB exposes PABS as an array : ]PTAB ( n -- addr ) 2* PABS + ; \ compute the VDP address for any PAB(n) : PAB[N] ( n -- VDPadr) 120 * 3FFF SWAP - ; : ?FILES ( n -- ) #FILES @ > ABORT" No more files" ; : NEWHNDL ( -- hndl) \ returns first free handle 0 \ start at handle=0 BEGIN 1+ DUP ?FILES \ have we exceeded #files allowed DUP ]PTAB @ \ fetch pab table contents 0= UNTIL ; \ loop until we find an empty location \ the file handle selects the active PAB : SELECT ( hndl -- ) DUP ?FILES ]PTAB @ DUP 0= ABORT" Null handle" ^PAB ! ; : ASSIGN ( hndl -- ) \ assign a new handle and SELECT it. DUP DUP PAB[N] SWAP ]PTAB ! SELECT ; : RELEASE ( hndl -- ) ]PTAB OFF 3FFF ^PAB ! ; \ INCLUDE assumes ^PAB starts at 3FFF. \ user level command. : FILES ( n -- ) DUP 8 > ABORT" too many files" #FILES ! ; .( ..) \ =================================== \ file access mode configuration VARIABLE FAM \ we build the file access mode in a variable \ and/or the contents of a variable with mask : AND! ( mask addr -- ) TUCK @ AND SWAP ! ; : OR! ( mask addr -- ) TUCK @ OR SWAP ! ; \ TI-99 file access mode modifiers 2 BASE ! \ *ctrl bits* : DISPLAY ( -- ) 11110111 FAM AND! ; : SEQUENTIAL ( -- ) 11111110 FAM AND! ; : RELATIVE ( -- ) 00000001 FAM OR! ; : UPDATE ( -- ) 11111001 FAM AND! ; : INPUT ( -- ) 00000100 FAM OR! ; : OUTPUT ( -- ) 00000010 FAM OR! ; : APPEND ( -- ) 00000110 FAM OR! ; VARIABLE B/REC \ bytes per record : VARI ( size -- fam) B/REC ! 00010000 FAM OR! ; : FIXED ( size -- fam) B/REC ! 11101111 FAM AND! ; \ set fam on stack to default file format \ (in case the op forgets to set it up) .( ..) HEX \ These ANS word adjust and return the FAM variable : R/W ( -- fam) UPDATE FAM @ ; : R/O ( -- fam) INPUT FAM @ ; : W/O ( -- fam) OUTPUT FAM @ ; \ ANS Forth word replaces INTERNAL : BIN ( fam -- fam') 8 OR ; \ modify FAM on stack \ needed to test for file args on stack : DEPTH ( -- n ) SP0 SP@ 2+ - 2/ ; \ : ?EXISTS ( -- ) \ FSTAT 8 AND \ IF DISKOFF TRUE ABORT" No such file" \ THEN ; .( ..) HEX \ build the PAB from all the pieces, error checking : OPEN-FILE ( $addr len fam -- fid ior) DEPTH 3 < ABORT" file args" NEWHNDL DUP >R ASSIGN \ copy handle & assign PAB [PAB PSIZE 0 VFILL \ erase the VDP PAB to be safe. ?DUP 0= \ is FAM 0 IF 14 THEN [PAB FLG] VC! \ write file access mode B/REC @ ?DUP 0= \ test for new record length IF 50 \ if not default to 80 bytes (>50) THEN [PAB RECLEN] VC! \ store reclen in PAB B/REC OFF \ reset the B/REC variable 2DUP MAKEPAB \ NEWFILE \ setup new file 0 FILEOP ( -- err#) \ call O/S OPEN DUP \ test for error IF R> RELEASE 0 SWAP \ release hndl. return 0 ELSE R> SWAP THEN ; : CLOSE-FILE ( fid -- ?) DUP SELECT 1 FILEOP SWAP RELEASE ; : READ-LINE ( c-addr u1 fid -- u2 flag ior ) SELECT 2 FILEOP DUP >R \ read operation, rpush error# IF \ if err#<>0 0 FSTAT R> \ fatal error, don't read data ELSE ( -- adr u1) [PAB CHARS] VC@ \ get no. chars read MIN >R \ MIN(u1,chars)= u2, rpush [PAB FBUFF] V@ SWAP R@ VREAD \ move VDP fbuff to c-addr R> \ get u2 (chars actually read) EOF 0= \ test EOF = 0 R> \ bring back error# THEN ; : WRITE-LINE ( c-addr u fileid -- ior ) SELECT DUP [PAB CHARS] VC! \ # chars to write ->PAB [PAB FBUFF] V@ SWAP VWRITE \ write CPU RAM to VDP file buffer 3 FILEOP \ call write operation FSTAT 2 AND FUSE \ fuse EOF and general file errors ; .( ..) : CREATE-FILE ( caddr len fam -- fid ior ) \ OUTPUT mode forces new file creation in TI-99 O/S 2 OR \ modify 'fam' bits to OUTPUT mode OPEN-FILE ; : FILE-POSITION ( fid -- n ior) SELECT [PAB REC#] V@ ERR@ ; : REPOSITION-FILE ( fid -- ior) SELECT [PAB REC#] V! 4 FILEOP ; : DELETE-FILE ( caddr len -- ior ) R/W OPEN-FILE ?FILERR 7 FILEOP ; \ =================================== 8 FILES \ set the #FILES now DECIMAL CR .( Max files set to ) #FILES @ . ( About 1080 bytes) HEX Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 21, 2018 Share Posted April 21, 2018 You may have already addressed this and maybe I am missing or forgetting something, but two things puzzle me about PAB and VRAM buffer placement in your handle-based file system for CAMEL99 Forth: The odd-address starting points referenced to >3FFF and The overwriting of the reserved disk buffer space of high VRAM tracked by DSRs at >8370 (highest available VRAM address). Disk DSRs, based on the TI DSR specs for the TI-99/4A, reserve buffer space for the DSR at the top of VRAM, placing the address of the byte just below this space into >8370. This buffer space changes for each invocation of the DSR’s FILES subprogram, changing the address in >8370 up or down by 518 bytes for each file (at least, that is so for TI, CorComp, MYARC(?), CF7 and nanoPEB DSRs). It seems to me that your upper reference point for PABs should be the value in >8370 after “ 8 FILES ” (or equivalent) is executed. If you have only tested your file-handle system on Classic99 with its default FIAD file handler, you can probably get away with it, but it will crash and burn on the real iron and emulators that use the actual TI-based DSRs. This will even happen on Classic99 if you use the TI controller option, which can only be invoked by using a disk image and manually editing the section of the INI file for that particular disk to set Type=3. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 21, 2018 Author Share Posted April 21, 2018 in order to shoehorn file loading into the 8k kernel I used a simple decrement the PAB pointer by >120 each time a new file is opened. This means the PAB pointer defaults to the top of VDP RAM at 3FFF before the first file is opened. So I think what your new information means for me if that I should replace my Forth variable with the address 8370 to properly tell the system that I have taken the VDP memory for myself. Did I get that right? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 21, 2018 Share Posted April 21, 2018 in order to shoehorn file loading into the 8k kernel I used a simple decrement the PAB pointer by >120 each time a new file is opened. This means the PAB pointer defaults to the top of VDP RAM at 3FFF before the first file is opened. So I think what your new information means for me if that I should replace my Forth variable with the address 8370 to properly tell the system that I have taken the VDP memory for myself. Did I get that right? Not unless you are writing your own DSR for peripheral I/O. Upon power-up, the top of VRAM is reserved by the DSR of the first disk device encountered by the 4A and its DSR handles calls for reserving more or less space by the FILES routine. The DSR uses that reserved space for passing file/sector contents to and from the programmer’s PABs and their associated buffers pointed to by bytes 2 and 3 of each PAB, which are distinct from the DSR’s upper-VRAM buffers. And, I still do not understand starting each PAB area on an odd address. Do you use a single byte at each starting address for linking or something else? Oh, wait!—VRAM is only ever byte-addressed, i.e, not directly address by the TMS9900!—never mind! ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 21, 2018 Author Share Posted April 21, 2018 So that is how the machine wakes up but if we load a program with the E/A cartridge, can we not take over the machine and do what we want with the VDP RAM? I am slowly working on getting my real iron running so I guess I get to find out in a while. B Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 21, 2018 Share Posted April 21, 2018 So that is how the machine wakes up but if we load a program with the E/A cartridge, can we not take over the machine and do what we want with the VDP RAM? I am slowly working on getting my real iron running so I guess I get to find out in a while. B Oh, you can, indeed, do whatever you want, just as long as you never attempt to open a file on disk. But—if you access a disk, the controller to which it is attached will use its reserved VRAM space and tromp all over whatever you may have put there. There is nothing you can do to tell the disk controller’s DSR to do otherwise short of disconnecting the controller, but, then, of course, you would have no disk access. In fact, if you trash the validation byte (>AA) just above the address in >8370, disk access may actually not work, at all. However, I do not know whether the DSR checks that byte before every I/O operation or only at startup to validate that it actually got written. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 22, 2018 Author Share Posted April 22, 2018 I thought the ROM DSR code used the PAB for its clues as to where the file buffer is located and which device to connect to and all the other details. I used to be confused, but now I am not so sure. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 22, 2018 Share Posted April 22, 2018 I thought the ROM DSR code used the PAB for its clues as to where the file buffer is located and which device to connect to and all the other details. I used to be confused, but now I am not so sure. That is mostly true, but the DSR has its own buffer in high VRAM for each open file, which must be different from the buffer to which the PAB points. The DSR does not check your PAB or the VRAM buffer to which it points to see whether the file is open. It checks its own buffer(s). I would need to review the details to be sure, but I believe the DSR always reads and writes whole sectors regardless of the read or write mode requested by the PAB. Whereas, the PAB’s buffer only needs to be big enough to hold one record, which can be much smaller than a sector. In fact, it even can make sense for two PABs to point to the same VRAM buffer for copying information from one file to another. The DSR, however, will use separate buffers for each file. I guess you could think of the DSR buffers as kind of dumbwaiters that pass file sectors back and forth. I think that, for writes, the DSR does not write a dirty sector buffer until a different sector is accessed or the file is closed. The fact that there is enough room in each DSR buffer for two sectors probably makes this process more efficient, but I digress... ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 22, 2018 Author Share Posted April 22, 2018 So the file system is double buffering in VDP Ram. Once at the sector level and then copying records into different VDP RAM. Sounds pretty inefficient, however I guess we can never accuse the TI-99 designers of worrying too much about efficiency. This could have been done using the (address, len) structure to manage the date, simply pointing to the data in the sector buffer rather than copying it anywhere. Maybe that's how I should write a new file system... hmmm Ok so I have to move my buffers much farther up in memory. But I still don't know where the FILES function is located when I use the E/A cartridge, that allocates this VDP sector memory. I may spend some time studying the DISK DSR CODE further. Thanks for the insights Lee. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 23, 2018 Share Posted April 23, 2018 So the file system is double buffering in VDP Ram. Once at the sector level and then copying records into different VDP RAM. Sounds pretty inefficient, however I guess we can never accuse the TI-99 designers of worrying too much about efficiency. This could have been done using the (address, len) structure to manage the date, simply pointing to the data in the sector buffer rather than copying it anywhere. Maybe that's how I should write a new file system... hmmm Ok so I have to move my buffers much farther up in memory. But I still don't know where the FILES function is located when I use the E/A cartridge, that allocates this VDP sector memory. I may spend some time studying the DISK DSR CODE further. Thanks for the insights Lee. No prob. I doubt that the E/A cartridge has a FILES routine. I think the power-up routine in the DSR sets the default to 3. The FILES function is a level 2 DSR routine. Its “name” is >16. Here is the FILES word’s routine for fbForth 2.0 that calls it: ;[*** FILES *** ( n --- ) * expects on the stack the maximum number * of simultaneously open files * DATA DPTH_N * FIL__N DATA 5+TERMBT*LSHFT8+'F','IL','ES'+TERMBT * FILES DATA $+2 * BL @BLF2A * DATA _FILES->6000+BANK2 _FILES MOV @$PABS(U),R0 ; PAB address LI R1,>0100 ; namelength (1 for DSR subroutines) LIMI 0 ; disable interrupts because VSBW and DSRLNK don't BLWP @VSBW ; write the byte to the PAB INC R0 ; next PAB address to write LI R1,>1600 ; FILES subroutine number in DSR BLWP @VSBW ; write to PAB MOVB @1(SP),@>834C ; get number of files from stack INCT SP ; pop stack DEC R0 ; point to namelength byte in PAB MOV R0,@SUBPTR ; copy to where DSR expects it BLWP @DSRLNK ; do the subroutine DATA >0A B @RTNEXT ; return to inner interpreter ;]* I am not checking for errors, but you can check the byte at >8350 for 0 (success) or failure (>FF). ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 23, 2018 Author Share Posted April 23, 2018 No prob. I doubt that the E/A cartridge has a FILES routine. I think the power-up routine in the DSR sets the default to 3. The FILES function is a level 2 DSR routine. Its “name” is >16. Here is the FILES word’s routine for fbForth 2.0 that calls it: ;[*** FILES *** ( n --- ) * expects on the stack the maximum number * of simultaneously open files * DATA DPTH_N * FIL__N DATA 5+TERMBT*LSHFT8+'F','IL','ES'+TERMBT * FILES DATA $+2 * BL @BLF2A * DATA _FILES->6000+BANK2 _FILES MOV @$PABS(U),R0 ; PAB address LI R1,>0100 ; namelength (1 for DSR subroutines) LIMI 0 ; disable interrupts because VSBW and DSRLNK don't BLWP @VSBW ; write the byte to the PAB INC R0 ; next PAB address to write LI R1,>1600 ; FILES subroutine number in DSR BLWP @VSBW ; write to PAB MOVB @1(SP),@>834C ; get number of files from stack INCT SP ; pop stack DEC R0 ; point to namelength byte in PAB MOV R0,@SUBPTR ; copy to where DSR expects it BLWP @DSRLNK ; do the subroutine DATA >0A B @RTNEXT ; return to inner interpreter ;]* I am not checking for errors, but you can check the byte at >8350 for 0 (success) or failure (>FF). ...lee Well this has forced me to read all the rest of the stuff on the TI Tech pages. Thanks again Lee. So It should be pretty simple now for me to call these subprograms by using the language I created for File DSRs. I believe I just need to search the sub-program list rather than the DSR list. That's the theory anyway. And we all know that theory and practice are the same ... in theory. (but not in practice) 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 23, 2018 Share Posted April 23, 2018 So It should be pretty simple now for me to call these subprograms by using the language I created for File DSRs. I believe I just need to search the sub-program list rather than the DSR list. Yup. That is what the BLWP @DSRLNK DATA >0A does with the >0116 (string length=1 and name=16h) in the PAB. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 28, 2018 Author Share Posted April 28, 2018 CAMEL99 Forth V2.0.11 I have addressed the new information (to me) that Lee provided regarding using >8370 as source of the end of VDP memory. I have not yet implemented "FILES" so the default value is currently set to 3 by the TI system and there is not way to change it. I am changing editors to ATOM to allow integration with GitHub, but I fear there will be some bad synchronization for a time while I get familiar with these new tools. However I am enjoying this modern way of doing things. :-) Version 2.0.11 binary is on GitHub in the DSK1 folder. There is also a major upgrade to the manual V0.7 that gives more insight for using the system with more demo programs, Assembler explanations and info on some new faster direct control (not auto-motion) Sprites. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 3, 2018 Author Share Posted May 3, 2018 Monkey Fingers You know what they say about monkeys and typewriters and an infinite amount of time? I am not sure it's true, but this monkey program is entertaining to watch if you are a word nerd. And if you write science fiction, it comes up with some pretty good character and planet names IMHO. The program has simple rules to prevent multiple consonants and vowels, but no rule for a 1 letter word that is just a consonant. This has been tested on CAMEL99 V2.0.11 \ monkeys.fth Brian Fox May 3 2018 \ INCLUDE DSK1.RANDOM.F DECIMAL VARIABLE WORD_LEN VARIABLE CHARSOUT VARIABLE WORDSOUT HEX 7FFF CONSTANT 32K : 1+! ( addr -- ) 1 SWAP +! ; : CLIP ( n min max -- n') ROT MIN MAX ; : VOWELS S" AEIOU" ; : BETWEEN ( n min max -- ? ) 1+ WITHIN ; : UALPHA? ( c -- ?) [CHAR] A [CHAR] Z BETWEEN ; : LOWER? ( c -- ?) [CHAR] a [CHAR] z BETWEEN ; : TOUPPER ( c -- c) DUP LOWER? IF 05F AND THEN ; DECIMAL : VOWEL? ( char -- ? ) VOWELS ROT SCAN NIP 0> ; : CONSONANT? ( char -- ? ) VOWEL? 0= ; VARIABLE PREVIOUS-CHAR \ PREVIOUS VALUES: -1=VOWEL, 0=UNDEFINED, 1=CONSONANT -1 CONSTANT AVOWEL 1 CONSTANT ACONST VARIABLE CONSONANTS VARIABLE VOWELS : NEW-WORD ( -- ) CONSONANTS OFF VOWELS OFF PREVIOUS-CHAR OFF ; : MONKEY-FINGER ( -- char) BEGIN 27 RND [CHAR] A + DUP UALPHA? UNTIL CHARSOUT 1+! ; : REMEMBER ( char -- ) DUP VOWEL? IF AVOWEL PREVIOUS-CHAR ! VOWELS 1+! CONSONANTS OFF ELSE ACONST PREVIOUS-CHAR ! CONSONANTS 1+! VOWELS OFF THEN ; : KILL|KEEP ( char ? -- char | ?) IF DROP FALSE ELSE TRUE THEN ; : GETVOWEL ( -- vowel-char) BEGIN MONKEY-FINGER DUP CONSONANT? KILL|KEEP UNTIL ; : GETCONST ( -- consonant-char) BEGIN MONKEY-FINGER DUP VOWEL? KILL|KEEP UNTIL ; : CONSONANTS? ( char n -- ?) CONSONANTS @ = PREVIOUS-CHAR @ ACONST = AND ; : VOWELS? ( char n -- ?) VOWELS @ = PREVIOUS-CHAR @ AVOWEL = AND ; \ Rules: \ never more than 2 vowels in a row \ never more than 1 consonants in a row : RULES ( CHAR -- CHAR ) 1 CONSONANTS? IF DROP GETVOWEL THEN 2 VOWELS? IF DROP GETCONST THEN REMEMBER ; \ 1 random key stroke, remember it and check rules , count char : TYPE-WRITER ( -- char) MONKEY-FINGER RULES ; : MONKEY-WORD ( -- ) NEW-WORD WORD_LEN @ RND 1+ 0 ?DO TYPE-WRITER EMIT LOOP WORDSOUT 1+! SPACE ; : TAB ( n -- ) VCOL ! ; : WAITKEYUP ( -- ) BEGIN KEY? 0= UNTIL ; : WAITKEY ( -- ) KEY? IF KEY DROP THEN ; DECIMAL : MONKEY-LINE ( -- ) CR MONKEY-WORD 13 TAB MONKEY-WORD 26 TAB MONKEY-WORD ; : TITLE PAGE CR 2 TAB ." IF..." CR CR 2 TAB ." an infinite number of monkeys, with" CR 2 TAB ." an infinite number of typewriters," CR 2 TAB ." type for an infinite amount of time," CR 2 TAB ." they will type the complete works" CR 2 TAB ." of Shakespeare." CR CR 29 TAB ." Anonymous" 10 23 AT-XY ." Press a key to begin..." KEY DROP ; : MONKEYS ( -- ) 27 7 VWTR TITLE PAGE CHARSOUT OFF WORDSOUT OFF 10 WORD_LEN ! CR ." Max word length = " WORD_LEN @ . BEGIN WAITKEY MONKEY-LINE CHARSOUT @ 32K = ?TERMINAL OR UNTIL WAITKEYUP CR CR ." The monkeys typed " CHARSOUT @ U. ." characters CR ." in " WORDSOUT @ . ." words." ; MONKEYFINGER.mp4 2 Quote Link to comment 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.