+Lee Stewart Posted March 13, 2018 Share Posted March 13, 2018 Ah yes the GROMs. Ok I will relent. On another matter. I have created Forth words to turn on the disk card and I can read the header, and search for DSR names. But from what I see in CLASSIC99 the address for DSK1 is >4800. However when I dump the ROM at address 4800 I see only zeros? What am I missing here? The screen shows my partially completed DSRLNK word operating... partially. Unless you are using a disk image with “Type=3” (read, “use TI disk controller”) in the “[Diskn]” section of Classic99.ini you are referencing, I do not believe you can rely on the information at >4000 to be what you expect. I monitored >4000 while loading TI Forth and stopped it with F1 when I saw the values change from all zeros. The address in question pointed to executable code in >4000 – >5FFF ROM space. ...lee Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3984316 Share on other sites More sharing options...
+Lee Stewart Posted March 13, 2018 Share Posted March 13, 2018 I should add that I suspect the code in Classic99 at >4000 for type 1 and 2 “disks” has only enough for your code to verify the header and to follow the DSR and subprogram lists for verification purposes. I am sure @Tursi will be by ere long to expound further upon this subject. ...lee Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3984318 Share on other sites More sharing options...
+TheBF Posted March 13, 2018 Author Share Posted March 13, 2018 (edited) Unless you are using a disk image with “Type=3” (read, “use TI disk controller”) in the “[Diskn]” section of Classic99.ini you are referencing, I do not believe you can rely on the information at >4000 to be what you expect. I monitored >4000 while loading TI Forth and stopped it with F1 when I saw the values change from all zeros. The address in question pointed to executable code in >4000 – >5FFF ROM space. ...lee OK. It is an emulator after all. I know it's a little crazy but when I look at Paolo's DSR code I see a lot of things that I already have in the system and so it grates against my "Forthyness" to replicate them. :-) For example here is the word to cut a string at the '.' character. : /DOT ( caddr len -- caddr len') \ cut string at the dot 2DUP [CHAR] . SCAN NIP - ; And here is the routine to find a DSR string in the ROM. : DSRFIND ( addr len -- link | 0) /DOT DEV$ PLACE 'DSRLIST ( -- >4008) BEGIN @ DUP 0= \ check for end of list SWAP DEV$ OVER >DSR$ =$ \ test string match in ROM ROT OR \ if either is true we're done. UNTIL ; These 2 routines are about 50 80(or so) LOC in Paolo's code. So that is my goal to remove the stuff that I can move into Forth and then only make the call with a small word in ALC. Edited March 13, 2018 by TheBF 3 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3984361 Share on other sites More sharing options...
Tursi Posted March 13, 2018 Share Posted March 13, 2018 (edited) On another matter. I have created Forth words to turn on the disk card and I can read the header, and search for DSR names. But from what I see in CLASSIC99 the address for DSK1 is >4800. However when I dump the ROM at address 4800 I see only zeros? What am I missing here? Classic99's DSR is simulated.. when the emulator detects the PC at >4800 with (or the low level subprogram addresses, which are >4820 and up) with the Classic99 disk controller mapped in (always at >1100 today), it jumps to a handler routine written in C++ that parses the PAB and takes the appropriate action, then returns the CPU back to the caller. There's no actual 9900 code involved. (Edit: the header at >4000 is 100% valid though, because the 9900 needs to parse that ) Edited March 13, 2018 by Tursi 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3984462 Share on other sites More sharing options...
+TheBF Posted March 13, 2018 Author Share Posted March 13, 2018 Classic99's DSR is simulated.. when the emulator detects the PC at >4800 with (or the low level subprogram addresses, which are >4820 and up) with the Classic99 disk controller mapped in (always at >1100 today), it jumps to a handler routine written in C++ that parses the PAB and takes the appropriate action, then returns the CPU back to the caller. There's no actual 9900 code involved. (Edit: the header at >4000 is 100% valid though, because the 9900 needs to parse that ) Excellent Thanks Tursi. And if I have not said it before, thank you so much for CLASSIC99. It has provide me with endless hours of fun and is and excellent Hack. B 1 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3984473 Share on other sites More sharing options...
+TheBF Posted March 15, 2018 Author Share Posted March 15, 2018 Small update for doing things the hard way. I have Forth code now that can scan a card and retrieve the entry address for the device routine. I am only scanning for 1 card at a time. My logic there is I know where the card is in the CRU map so why waste time? The code is factored into small pieces so when I need to scan devices on another card it's trivial to do so. \ DSKCARD a constant ie: the CRU address of the card (>1100) ?CARDOFF ( if R12<>0 then turn that device off) DSKCARD Enable ?CARDID ( abort with message if we don't >AA) DSRFIND DUP ?DEVERR ( abort with message if don't find the device) \ so to search the serial CARD would be HEX ?CARDOFF 1300 Enable ?CARDID DSRFIND DUP ?DEVERR \ so cards will be enabled by the hi-level API for different devices. The code creates the PAB and updates the addresses at >8355 and >8356 as well but I am struggling to understand what this crazy little machine needs to call the device service code properly. If I can get the calling sequence sorted out I think I have a DSR written in a high level language with just a little ALC. <THEME_MUSIC> "Dream... Dream, dream, dream... </THEME_MUSIC> Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985570 Share on other sites More sharing options...
+Lee Stewart Posted March 15, 2018 Share Posted March 15, 2018 The code creates the PAB and updates the addresses at >8355 and >8356 as well but I am struggling to understand what this crazy little machine needs to call the device service code properly. I am not sure I understand the problem. DSR device routines [type 8] are pretty straightforward most of the time, but DSR subprograms [type >A] can, indeed, be difficult to sort out. For type 8 DSR calls: the PAB must be properly set up for the call (open, read, write, ...) the address of the PAB filename length byte is stored at >8356 the DSRLNK call searches for the device name in the device list of each DSR card the entry point address in front of the found device name is executed with BL [or error if no device name is found in any DSR card] upon return, process the PAB error flags return to the routine that called DSRLNK. For type >A DSR calls, things can get a little messy: the PAB must be set up with the length byte of the subprogram name followed by the subprogram name (name of the level 1, read/write sectors subprogram name is >10, so the PAB contains only >0110) the file transfer block info for the desired operation must be properly set up (this depends on the subprogram, but is usually at FAC or FAC+2, i.e., >834A or >834C there may also be an “additional information” block required, which can be located at any desired CPU RAM) the DSRLNK call searches for the subprogram name in the subprogram list of each DSR card the entry point address in front of the found subprogram name is executed with BL [or error if no subprogram name is found in any DSR card] the subprogram returns an error code at >8350 return to the routine that called DSRLNK. I do not know whether something in the above verbiage is what you are seeking, but maybe it will lead you somewhere. ...lee 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985662 Share on other sites More sharing options...
+TheBF Posted March 15, 2018 Author Share Posted March 15, 2018 That's how I understood things too. Thank you for that succinct explanation. I have the PAB set up actually per the E/A Manuals file example. I created DSK1.DATA with BASIC so it's there. The ASM version of the program indeed finds the file and and displays the contents on the screen. So with your explanation and give the fact that I have found the device entry for DSK1 I should only need to: Create a DSR workspace Create a vector "DODSR" with the DSR workspace & a program that does a BL to the dev entry address BLWP @ DODSR which runs the BL to the device entry address RTWP back to Forth Examine the PAB status to see what happened. Does that sound correct? Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985814 Share on other sites More sharing options...
+Lee Stewart Posted March 15, 2018 Share Posted March 15, 2018 Pretty much. Does DODSR do a change to the GPL workspace before turning on the cards and back to your DSR workspace upon return from the BL to dev entry address? ...lee Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985833 Share on other sites More sharing options...
+TheBF Posted March 15, 2018 Author Share Posted March 15, 2018 Pretty much. Does DODSR do a change to the GPL workspace before turning on the cards and back to your DSR workspace upon return from the BL to dev entry address? ...lee At this point no, but that is the kind of thing I am missing in the calling protocol. It seems like it has been followed like a recipe over the years. I am looking for the minimal ALC needed to call the routine. :-) Not sure what the GPL workspace needs to do if I have already discovered the entry address in the ROM? I am trying what I wrote above now. Will let you know how it goes. Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985835 Share on other sites More sharing options...
+TheBF Posted March 15, 2018 Author Share Posted March 15, 2018 Well you definitely need to be in the GPL workspace to BL *R9. So I did this: CODE CALLDSR ( -- ) 83E0 LWPI, \ change to GPL workspace *R9 BL, \ GPL R9 already has the entry address DSRWKSP LWPI, RTWP, ENDCODE And I got back home with an OK prompt ... but the interpreter had stopped. One step closer. Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3985871 Share on other sites More sharing options...
+TheBF Posted March 15, 2018 Author Share Posted March 15, 2018 Minor progress on DSRLNK the hard way. So here is the code that returns to Forth safely. When I look at the ROM listings I think the fact that it returns to R11+2 means there was an error. Nothing happens in the PAB so I have a few more chicken entrails to examine. :-)) CODE: CALLDSR ( -- ) 83E0 LWPI, \ change to GPL workspace *R9 BL, \ GPL R9 already has the entry address $$ JMP, \ Return here if correct? DSRWKSP LWPI, \ Returns here if error ? RTWP, \ Return to Forth NEXT, END-CODE To call the 9900 style VECTOR I also made a new FORTH word in the system called ... what else...BLWP! It allows me to put a vector on the Forth stack and bullwhip right into it. That's pretty cool. CODE: BLWP ( vector -- ) *TOS BLWP, TOS POP, NEXT, END-CODE \ make a 9900 vector that we call with BLWP \ workspace compile program address \ --------- ----------------------- CREATE DSKLNK DSRWKSP , ' CALLDSR >BODY , \ Usage: DSKLNK BLWP I have a dream. That one day, little CAMEL Forths, will be able to access the TI file system with minimal Assembly language code. 3 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986107 Share on other sites More sharing options...
Tursi Posted March 15, 2018 Share Posted March 15, 2018 R11+2 means it was successful, actually. I have some debug in Classic99 that is emitted when you call a DSRLNK with improper settings (meant to help debug code that talks TO dsrs...), let me see what I check there... - Workspace must be GPLWS (0x83E0). Numerous DSRs assume and rely on this - >83D0 should contain the CRU base of the DSR (I can't remember the reason for this, but something I considered important relied on it - I want to say not just boot tracking) - DSR name length must be in >8354 as a word (just the device part, ie: DSK1 is >0004) - this is used to parse the PAB. Must be 1-7 characters Then there's some PAB tests and stuff that doesn't really affect what you're trying to do. I guess I should note too that the tests in Classic99 are /after/ DSRLNK, for the actual DSR call itself. Somewhere on this forum is posted TI's official DSR spec, too, meant for writing compatible DSRs. That may help? 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986135 Share on other sites More sharing options...
apersson850 Posted March 15, 2018 Share Posted March 15, 2018 (edited) I noticed when I tried to get the Horizon RAM-disk to work with the p-code card, that the ROS for that card made assumptions about what the usual DSRLNK code, the one TI have taught us to write, does with memory. The DSR is looking at memory at locations where the "standard" DSR does store them. But the p-code card has a completely different way of handling DSR calls. It does (of course) follow TI's rules for DSR calls, but only the expressed rules. So the point of this post is that if you do DSR calls in a way that differs from the standard one, if you try to be smarter (the p-code card's code is more clever), then you'll find certain cards stop working. Edited March 15, 2018 by apersson850 1 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986208 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 R11+2 means it was successful, actually. I have some debug in Classic99 that is emitted when you call a DSRLNK with improper settings (meant to help debug code that talks TO dsrs...), let me see what I check there... - Workspace must be GPLWS (0x83E0). Numerous DSRs assume and rely on this - >83D0 should contain the CRU base of the DSR (I can't remember the reason for this, but something I considered important relied on it - I want to say not just boot tracking) - DSR name length must be in >8354 as a word (just the device part, ie: DSK1 is >0004) - this is used to parse the PAB. Must be 1-7 characters Then there's some PAB tests and stuff that doesn't really affect what you're trying to do. I guess I should note too that the tests in Classic99 are /after/ DSRLNK, for the actual DSR call itself. Somewhere on this forum is posted TI's official DSR spec, too, meant for writing compatible DSRs. That may help?t Thanks for all the detail Tursi. I managed to extract those things from Paolo's DSR code. I think I am doing them right. And my code is consistently returning via R11+2 so it must be close. I may be removing the CRU base from 83D0 too soon. I will play around with that. I have most of the TI Docs here, but I missed subtle details when reading the text sometimes. It's part of the fun. :-) Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986266 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 I noticed when I tried to get the Horizon RAM-disk to work with the p-code card, that the ROS for that card made assumptions about what the usual DSRLNK code, the one TI have taught us to write, does with memory. The DSR is looking at memory at locations where the "standard" DSR does store them. But the p-code card has a completely different way of handling DSR calls. It does (of course) follow TI's rules for DSR calls, but only the expressed rules. So the point of this post is that if you do DSR calls in a way that differs from the standard one, if you try to be smarter (the p-code card's code is more clever), then you'll find certain cards stop working. I have no doubt about being clever breaking stuff. Thanks for the polite warning. :-) (I made a career out this kind of behavior in business, where I was accused of being "innovative". Business weenies don't always like that.) I am trying to "follow" the rules whilst doing the grunt work of moving data into memory and such with Forth. As noted cutting a string at the '.' character and things like that are already written or a least the factors are written so cobbling the primitives together actually adds less code in some cases than re-writing everything in Assembler. When the whole thing works in some fashion I will post the low level code and the High level API that I come up with. My end goal is my own amusement and ultimately I want to implement the file word set or a functional subset thereof for ANS/ISO Forth. It's going to be a challenge to map a modern file command set to the old TI file system, but the standard makes allowances for "system dependencies" in this area thank goodness. Thank you for weighing in on my toils. It makes it easier to live with myself and this somewhat strange pursuit that I am helpless to stop. B 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986271 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 DSR opcode >0 on PAB >0F89, filename Releasing file buffer 0 Recycling unclosed file buffer 0 Opening DSK10.DSK1.DATA on drive type ClipBoard PAB requested file type is DF0 Allocating clipboard buffer (0) Clipboard read 95 records Restore set record number to 0 Thanks for this feature Tursi. I was looking at dis-assembled code and my eyes were getting crossed. This is showing me all the errors! Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986284 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 IT Finally WORKS! Big thanks to Lee, Willsy, Tursi and anyone else I might have forgotten who added their inputs. I have a working Disk only DSRLNK with most of it programmed in Forth. The code is pretty ugly yet but the big thing that I learned was the PAB address that we give normal DSR is NOT the PAB address that the DSR uses. What???? Very odd, however the PAB address must start at the position of the '.' after the device name. I accomplish this in Forth with a few simple words. _FNAME computes the address of the file name from a VDP or CPU ram address. (addr+9) /DOT Takes a stack string (addr,len) and computes a new string upto the location of the '.' char. in BASIC it's like: SEG$(A$,1,POS(A$,".")) but a little faster. (ok a lot faster) CREATEPAB ( text,len -- the-real-pab-address) copies a pab buffer from CPU ram to a clean PAB address in VDP RAM and returns the "real PAB address" that begins at the first dot location in the string. : _FNAME ( PAB -- PAB+9) 9 + ; \ compute the filename location : /DOT ( caddr len -- caddr len') \ cut input string at the dot 2DUP '.' SCAN NIP - ; \ createpab does setup per e/a manual AND computes the \ PAB address of the "DSK?.filename" without the device: \ EXAMPLE: DSK1.TEST becomes .TEST \ usage: S" DSK1.DATA" CREATEPAB : CREATEPAB ( addr len -- real-PAB-addr) 2DUP \ dup the string info PDATA _FNAME PLACE \ place the string in PDATA buffer PAB PSIZE 0 VFILL \ erase VDP PAB memory PDATA PAB PSIZE VWRITE \ write PDATA to VDP PAB /DOT NIP 1+ ( -- n) \ compute offset upto '.' \ (nip string address. we don't need it) PAB _FNAME + ; \ add offset to PAB _FNAME \ *this is the REAL PAB address that \ DSR uses!!! Opening a file is pretty ugly at the moment the comments explain the FORTHisms. : OPEN ( $addr len -- ) \ *STACK PICTURE* 2DUP CREATEPAB ( -- $addr len realpab) -ROT ( -- realpab $addr len ) DiskON ?CardID \ abort if card is not 'AA' DSRFIND ( -- realpab link) DUP ?DEVERR \ ABORT if link=0 DUP >DSR$ ( -- link $) \ link->DSR$ ie: the name of the DSR C@ 8355 C! \ len(DSR$) -> hex8355 ( -- link) >ENTRY 83E0 9 REG# ! \ convert link to DSR entry -> GPL.R9 ( -- realpab ) 8356 ! \ the "REAL" PAB file name stored here 0 PAB VC! \ set the PAB to open opcode DSKLNK BLWP \ open the file ; And the only ALC is CALLDSR . It's written in the cross-compiler's Forth and Assembler dialect. I am not 100% sure, but it could be simplified by removing the its local workspace but keeping it this way means any TASK in CAMEL99 could call it from it's own task workspace and get home safely. VARIABLE: DSRWKSP [CC] 20 TALLOT [TC] CODE: CALLDSR ( -- ) 83E0 LWPI, \ change to GPL workspace *R9 BL, \ GPL R9 already has the entry address @@1 JMP, @@2 JMP, @@1: DSRWKSP @@ SETO, \ return true flag IN R0 if there is an error @@2: DSRWKSP LWPI, \ Returns here if error ? RTWP, \ Return to Forth NEXT, END-CODE 3 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986670 Share on other sites More sharing options...
+Lee Stewart Posted March 16, 2018 Share Posted March 16, 2018 Looking good! Have you ever looked at the TI Forth code for file I/O? I converted it to nearly all ALC for fbForth 2.0, but the Forth code might be instructive if you have not seen it. It is in blocks 68 – 71 of the TI Forth system diskette. Here is the Forth code from blocks 68 – 71: ( FILE I/O ROUTINES 12JUL82 LCT) ( Requires LOADing Screen #33, "System Synonyms") HEX 0 VARIABLE PAB-ADDR 0 VARIABLE PAB-BUF 0 VARIABLE PAB-VBUF : FILE <BUILDS , , , DOES> DUP @ PAB-VBUF ! 2+ DUP @ PAB-BUF ! 2+ @ PAB-ADDR ! ; : GET-FLAG PAB-ADDR @ 1+ VSBR ; : PUT-FLAG PAB-ADDR @ 1+ VSBW ; : SET-PAB PAB-ADDR @ DUP 0A 0 VFILL 2+ PAB-VBUF SWAP 2 VMBW ; : CLR-STAT GET-FLAG 1F AND PUT-FLAG ; : CHK-STAT GET-FLAG 0E0 AND 837C C@ 20 AND OR 9 ?ERROR ; : FXD GET-FLAG 0EF AND PUT-FLAG ; : VRBL GET-FLAG 10 OR PUT-FLAG ; HEX : DSPLY GET-FLAG 0F7 AND PUT-FLAG ; : INTRNL GET-FLAG 8 OR PUT-FLAG ; : I/OMD GET-FLAG 0F9 AND ; : INPT I/OMD 4 OR PUT-FLAG ; : OUTPT I/OMD 2 OR PUT-FLAG ; : UPDT I/OMD PUT-FLAG ; : APPND I/OMD 6 OR PUT-FLAG ; : SQNTL GET-FLAG 0FE AND PUT-FLAG ; : RLTV GET-FLAG 1 OR PUT-FLAG ; : REC-LEN PAB-ADDR @ 4 + VSBW ; : CHAR-CNT! PAB-ADDR @ 5 + VSBW ; : CHAR-CNT@ PAB-ADDR @ 5 + VSBR ; : REC-NO DUP SWPB PAB-ADDR @ 6 + VSBW PAB-ADDR @ 7 + VSBW ; : N-LEN! PAB-ADDR @ 9 + VSBW ; HEX ( COMPILE A STRING WHICH IS MOVED TO VDP-ADDR AT EXECUTION) : (F-D") PAB-ADDR @ 0A + R COUNT DUP 1+ =CELLS R> + >R >R SWAP R VMBW R> N-LEN! ; : F-D" 22 STATE @ IF COMPILE (F-D") WORD HERE C@ 1+ =CELLS ALLOT ELSE PAB-ADDR @ 0A + SWAP WORD HERE COUNT >R SWAP R VMBW R> N-LEN! ENDIF ; IMMEDIATE HEX : DOI/O CLR-STAT PAB-ADDR @ VSBW PAB-ADDR @ 9 + 8356 ! 0 837C C! DSRLNK CHK-STAT ; : OPN 0 DOI/O ; : CLSE 1 DOI/O ; : RD 2 DOI/O PAB-VBUF @ PAB-BUF @ CHAR-CNT@ VMBR CHAR-CNT@ ; : WRT >R PAB-BUF @ PAB-VBUF @ R VMBW R> CHAR-CNT! 3 DOI/O ; : RSTR REC-NO 4 DOI/O ; : LD REC-NO 5 DOI/O ; : SV REC-NO 6 DOI/O ; : DLT 7 DOI/O ; : SCRTCH REC-NO 8 DOI/O ; : STAT 9 DOI/O PAB-ADDR @ 8 + VSBR ; The above code relies on DSRLNK code written in ALC that is identical to E/A code and practically identical to Paolo’s code, as near as I can tell. If you need the code for the system synonyms or other code used by the above, I will post it as soon as I can. ...lee Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986725 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 (edited) LOL. You are reading my mind. Thank you. I had played with some of this before and I am just testing my ideas now. The Forth Standard specifies something called a "file access method" (FAM) So CREATE-FILE is defined as: CREATE-FILE ( c-addr u fam -- fileid ior ) There are also 3 words, R/W R/O W/O that return the "FAM". I was struggling with how to do this with all the variations possible in the 99-4a file system. Just recently I had a small epiphany. So here is what I came up with. The file mode control words assemble all the bits that define a file in a variable called, what else FAM. 2 BASE ! VARIABLE FAM \ we build the file mode bits in this variable : FAM@ FAM @ ; : FAM! FAM ! ; \ mask bits added bits store \ --------- ----------- -------- : DISPLAY ( -- ) FAM@ 11101111 AND FAM! ; \ Text file : INTERNAL ( -- ) FAM@ 00010000 OR FAM! ; \ binary file : VARI ( -- ) FAM@ 11110111 AND 00001000 OR FAM! ; \ VARIABLE is a keyword in Forth : UPDATE ( -- ) FAM@ 11111001 AND FAM! ; : OUTPUT ( -- ) FAM@ 11111001 AND 00000010 OR FAM! ; : INPUT ( -- ) FAM@ 11111001 AND 00000100 OR FAM! ; : APPEND ( -- ) FAM@ 00000110 OR FAM! ; : SEQUENTIAL ( -- ) FAM@ 11111110 AND FAM! ; : RELATIVE ( -- ) FAM@ 00000001 OR FAM! ; : fixed ( -- ) FAM@ 11110111 AND FAM! ; HEX \ set record length and set mode for FIXED files : FIXED ( c --) PAB 4 + V! fixed ; These are doing exactly the same thing as the TI-Forth code but are keeping track inside the FAM variable instead of in the FLAGS field in the PAB. Then I defined the ANS words like this: \ ANS/ISO Forth FILE ACCESS METHODs (FAM) : R/W ( -- fam) UPDATE FAM @ ; : R/O ( -- fam) INPUT FAM @ ; : W/O ( -- fam) OUTPUT FAM @ ; So I figure you can type file mode words until the cows come home and then when you create-file or open-file etc. you just insert the R/W or whatever and the hi-level word takes care of it. This is as far as I have gotten . I refactored the pab creation and magic address writing to the word NEWFILE just now. Then I made my file operations all lowercase primitives ( open,read,write,close etc.) They just fill in the OPCODE in PAB and do the BLWP magic and return the error bits to the stack. Then the final interface will look like ANS Forth. (UNTESTED!) Once it's working I will get to file handles for 3 files. "Make it work first" : CREATE-FILE ( c-addr u fam -- fileid ior ) \ fam is the "read/write" file access method. -ROT NEWFILE FLG! \ create PAB, set the file mode open ( -- err) \ call open primitive 1 SWAP ; \ return a file id (ALWAYS 1) and error As you can see I had lots of time to dream about the innards before I could make it work. That only took me oh... well let's say... I started thinking about it a year ago. As I look at the TI-Forth code I can probably simplify further. And I see that need to fix my error words. Thanks again for all your support. It makes a real difference. Edited March 16, 2018 by TheBF 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986762 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 (edited) A Disk ONLY DSRLINK in (Mostly) Forth Here is the DSR Link code itself just for the record after all my jaw-wagging. There is general principle from Chuck Moore the inventor of Forth that every word should have one function. The large search through all the cards model of the classic DSR is not consistent with that thinking. Since we know the normal address of the Expansion unit's disk card I chose to only search that card. The code is factored in such a way that I can create a serial comm. card or another card DSR very easily when I need it. The result is that the device searches are fast and specific. This is perhaps more important here since the search is in Forth and not Assembler. Edit: This adds 390 bytes to the Forth system which includes the names of all the words and the linkage headers. HEX 1100 CONSTANT DSKCARD \ No need to scan for the Floppy DISK CARD. It's here 4000 CONSTANT 'ID \ DSR ROM ID = >AA 4008 CONSTANT 'DSRLIST \ start of linked list of DSR devices CREATE DEV$ 8 ALLOT \ DEV$ holds the counted string left of the '.' : >DSR$ ( link -- $) 4 + ; \ convert list link to DSR$ : =$ ( $1 $2 -- flag) OVER C@ 1+ S= 0= ; \ compare 2 counted strings \ DSRFIND searches for a matching device NAME in the DSR ROM \ It returns the device's link-field. ( code address is in the next CELL) : DSRFIND ( addr len -- link_addr) /DOT DEV$ PLACE \ cut input string, copy to DEV$ 'DSRLIST \ 1st LINK in ROM DSR linked list BEGIN @ \ fetch the next link DUP 0= \ test for end of list SWAP DEV$ OVER >DSR$ =$ \ test string match in ROM ROT OR \ if either is true we're done. UNTIL ; \ card control lexicon : Enable ( CRU -- ) CRU@ OVER <> \ fetch CRU (R12), is this a new card? IF 0 SBZ \ if so, turn it off THEN CRU! 0 SBO ; \ then turn on the requested card : Disable ( CRU -- ) CRU! 0 SBZ ; \ diskcard control : DiskON ( -- ) DSKCARD DUP 83D0 ! Enable ; \ CRU copied to 83D0 (magic) : DiskOFF ( -- ) DSKCARD Disable ; \ DSR error handlers : ?CardID ( -- ) 'ID C@ AA <> ABORT" CARD not enabled" ; : ?DEVERR ( link -- ) 0= ABORT" Device not found" ; \ primitives that convert something to another thing : REG# ( workspace n -- addr) CELLS + ; \ addr is Register n in workspace : >ENTRY ( DSRlink -- entry_addr) CELL+ @ ; \ DSKLNK is DISK ONLY dsrlink. Simpler than general purpose. \ make a 9900 vector that we call with BLWP \ workspace ALC program address \ --------- ----------------------- CREATE DSKLNK DSRWKSP , ' CALLDSR >BODY , \ ---------------- END OF DSR ------------------------ And the only ALC is here VARIABLE: DSRWKSP [CC] 20 TALLOT [TC] CODE: CALLDSR ( -- ) 83E0 LWPI, \ change to GPL workspace *R9 BL, \ GPL R9 already has the entry address @@1 JMP, \ Returns here if error ? @@2 JMP, @@1: DSRWKSP @@ SETO, \ return true flag IN R0 if there is an error @@2: DSRWKSP LWPI, RTWP, \ Return to Forth NEXT, END-CODE Edited March 16, 2018 by TheBF 2 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986839 Share on other sites More sharing options...
+Lee Stewart Posted March 16, 2018 Share Posted March 16, 2018 I should add that the DSRLNK of the TI Forth code I posted above includes “type 8” as part of the call. Also, I can add the stack effects to the Forth words for the TI Forth code, if you like. I might do it anyway—it’s not like I am strapped for time. | ...lee Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986872 Share on other sites More sharing options...
+TheBF Posted March 16, 2018 Author Share Posted March 16, 2018 I should add that the DSRLNK of the TI Forth code I posted above includes “type 8” as part of the call. Also, I can add the stack effects to the Forth words for the TI Forth code. if you like. I might do it anyway—it’s not like I am strapped for time. | ...lee No need for stack pictures. It all makes sense to me now. And... it's very helpful. Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986918 Share on other sites More sharing options...
RXB Posted March 17, 2018 Share Posted March 17, 2018 (edited) At this point no, but that is the kind of thing I am missing in the calling protocol. It seems like it has been followed like a recipe over the years. I am looking for the minimal ALC needed to call the routine. :-) Not sure what the GPL workspace needs to do if I have already discovered the entry address in the ROM? I am trying what I wrote above now. Will let you know how it goes. You should know that ALC DSR is limited to just ROM and is incapable of finding other DSR devices. i.e. GPL DSR, Devices that use GPL DSR or do you have access to GPL device listings. A good example is using GPL I can catalog Hard Drives or RAM DISK or Disk drives with less code. Also as GPL finds all devices you would need to really load up a ton of code to do this in Assembly. It is just more effective and less costly in RAM to use GPL DSR for devices. Edited March 17, 2018 by RXB Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3986974 Share on other sites More sharing options...
+TheBF Posted March 17, 2018 Author Share Posted March 17, 2018 You should know that ALC DSR is limited to just ROM and is incapable of finding other DSR devices. i.e. GPL DSR, Devices that use GPL DSR or do you have access to GPL device listings. A good example is using GPL I can catalog Hard Drives or RAM DISK or Disk drives with less code. Also as GPL finds all devices you would need to really load up a ton of code to do this in Assembly. It is just more effective and less costly in RAM to use GPL DSR for devices. I have know doubt using GPL is more space efficient. It's the machines native O/S language. And from what I have seen in your videos one can do anything with GPL and you especially so. I should be able to re-use some of these Forth routines to get to GPL routines. (?) Programming Forth works it's very much like you're creating a "GPL" in that you are building a set of language operations that let you do more with less code as you go along. I may have to create a more comprehensive scanner to find things, but I think it's doable but it will have to wait until I get past this job. 1 Quote Link to comment https://forums.atariage.com/topic/262846-dsrlink-code-tutorial/page/3/#findComment-3987037 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.