+Lee Stewart Posted October 28, 2018 Share Posted October 28, 2018 I might have found a bug in CLASSIC99 when using TYPE 3 disks or I still don't understand things. I was working over my DSRLNK and it worked perfectly when reading the file status field in the PAB while using TYPE 1 and TYPE 2 disks. But with a type three disk I never got a change in status when I hit the EOF. I spent a long time cursing my inability to find the problem in the Asm code. In desperation I wanted to see what I was missing so I ran the equivalent program in BASIC and... it doesn't seem to find the EOF bits in the status flag either. Here is the BASIC program: 100 REM CATALOG DISK PROGRAM 110 PRINT "Input DSKx. :"; 120 INPUT DSK$ 130 OPEN #1:DSK$,INPUT ,INTERNAL,RELATIVE 140 INPUT #1:N$,X,Y,Z 150 PRINT N$,X;Y;Z 160 GOTO 140 170 CLOSE #1 180 END Run it and INPUT a type 1 or 2 disk and it will error out on 140. But on a type 3 disk it runs forever, just like my Forth programs. Is my analysis correct? I am not sure you have chosen the best example file for this topic. DSKx.CATALOG is not a real file. The DSR provides the user with exactly 128 “records” with null strings for nonexistent file names. These are always presented alphabetically with the null records at the end. This allows you to abort reading records at the first record with a null filename string, which is how I do it in fbForth 2.0 (ported from TurboForth). Having not yet analyzed the DSR routine that generates the “file”, I cannot say how it may differ from normal file access. The above notwithstanding, I did try to dig through the DSR’s READ routine to see if it handled VARIABLE files differently from FIXED files regarding incrementing the PAB to the next record to be read. I think it does, but I was having a little trouble following the ALC. I do know that, for RELATIVE files in TI Basic, TI recommended to use a method different from EOF to check for the last record read. I would also say that the fault for the failure of your code to error out when it passed the end of file may lie more with TI Basic’s INPUT than with the DSR’s READ routine. I say this partly because the DSR’s READ routine only seems to distinguish between VARIABLE and FIXED files, not whether they were opened in SEQUENTIAL or RELATIVE mode. Of course, I may have missed something. I would certainly try your code on a file of your own making before concluding there is a problem with Classic99. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 28, 2018 Author Share Posted October 28, 2018 (edited) OK that makes sense. I thought that all files would report EOF the same way. I see now that the directory is a fixed length file with empty records. So I can change my disk directory utilities to test for a null file name. Simple. Thanks Lee But for the record, Classic99 reports an EOF with type 1 and type 2 files. Edited October 28, 2018 by TheBF Quote Link to comment Share on other sites More sharing options...
Tursi Posted October 29, 2018 Share Posted October 29, 2018 "Type 1" and "Type 2", being FIAD and DOAD, are DSRs that I wrote, that (originally, at least) behave like I believe a DSR should. All input is through the PAB, and all behaviors run through standard interfaces. "Type 3" runs the TI disk controller ROM, which everyone else considers perfection. Directories are handled very differently from files there. Your code is just hoping that a file error will stop it. With a quick look at the disk DSR, it appears it will report EOF after 128 records are read, without regard to how many files are on the disk. It DOES check whether it's out of files, and if it is, then yeah, it /explicitly/ returns the zero size record instead of EOF. I suppose I could make my DSR work that way too, but it seems kind of dumb. Still, I'll take a note. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 29, 2018 Author Share Posted October 29, 2018 As long as we know it's not a big deal to be sure. While I am here, I notice that the DSR code I took from here clears R1 and then does INC R1 before it does the BL *R9. Is that something that other programs use to count the entries into the DSR? It doesn't seem to make a difference if I comment those 2 lines out. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 29, 2018 Share Posted October 29, 2018 As long as we know it's not a big deal to be sure. While I am here, I notice that the DSR code I took from here clears R1 and then does INC R1 before it does the BL *R9. Is that something that other programs use to count the entries into the DSR? It doesn't seem to make a difference if I comment those 2 lines out. R1 is only important if the caller of DSRLNK cares which instance of a device/program routine was run. R1 will only ever contain 1 if the first hit on the name search runs successfully and takes the normal return by performing “INCT R11” before returning. A DSR may actually contain the device/program name sought, but refuse to run it or otherwise take the error return immediately following “BL *R9”, i.e., not do the normal “INCT R11” before returning. If the error return is taken, the same DSR search continues until the device/program is either found again (a duplicate name[?]) or the list is exhausted. If the list is exhausted, the next DSR ROM is searched. If the name is found in any of these subsequent searches, R1 is incremented and saved as are the new entry point and CRU. Once a device/program routine is run to completion with the normal return, R1 is likely trashed, but the caller of DSRLNK can use the saved value of R1 to discover which instance of the device/program routine was run as well as its entry point and which card (by its CRU) did the deed from the other saved values. The saved values that appear unimportant because they are not actually used in the E/A-type DSRLNK may have been put there for debugging purposes or future use. I agree with your conclusions that they are not critical to your current programming, but, with the exception of the saved R1, they certainly could be used to shorten file access for already open files. Saving R1 appears only useful as a debugging tool. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 29, 2018 Author Share Posted October 29, 2018 (edited) Your knowledge of this machine is always amazing Lee. I tried a version without GPL R1 being incremented before each call and it messed up sometimes so It stays. For anyone who's interested here is the current DSR Link I am using, re-written for the XFC99 cross-assembler. It seems to work pretty well now. I replaced some jumps with structured loops and if/endif which helps me see the shape of the code. There are conditions where the code jumps out of the structured loops. I left these alone because a complete re-write is needed if I wanted it "pretty". (make it work, then make it better) EDIT: The original posted version was un-reliable due to me trying to keep interrupts on in part of DSRLNK code. I have re-posted the reliable version. Interrupts are disabled while the code runs. \ DSRLNK for XFC99 cross-compiler/Assembler \ PASSES error code back to Forth workspace, TOS register \ Source: \ http://atariage.com/forums/topic/283914-specialized-file-access-from-xb/page-2 \ by InsaneMultitasker via Thierry Nouspikel CROSS-ASSEMBLING XASSEMBLER DEFINITIONS \ we need more labels than I normally use for Forth style CODE Words A DUP refer: @@A binder: @@A: CROSS-COMPILING XASSEMBLER DEFINITIONS \ MACRO to simplify the VDP code : VDPWA, ( reg -- ) DUP SWPB, \ setup VDP address DUP VDPWA @@ MOVB, DUP SWPB, VDPWA @@ MOVB, NOP, ; : [TOS] 8 (R13) ; \ gives access to Forth top of stack register [CC] HEX TARGET-COMPILING \ 8C02 EQU VDPWA \ 8C00 EQU VDWWD \ 8800 EQU VDPRD l: HEX20 20 BYTE, l: HEXAA AA BYTE, l: PERIOD 2E BYTE, \ '.' .EVEN l: NAMBUF BSS 6 \ no header string space l: H2000 DATA 2000 l: CYC1 DATA 0000 l: H1300 DATA 1300 \ take some space in Forth DATA stack for a workspace [CC] SP0 100 - [TC] VALUE: DREGS [CC] 5 2* DREGS + [TC] EQU DREG(5) CLR-JMPTABLE l: DSR1 \ headless code *R14+ R5 MOV, \ get '8'->R5, auto inc for return HEX20 @@ R15 SZCB, \ >20 eq flag=0 8356 @@ R0 MOV, \ [PAB FNAME] to R0 R0 R9 MOV, \ dup R0 to R9 R9 -8 ADDI, \ R9-8 = [PAB FLG] R0 VDPWA, VDPRD @@ R1 MOVB, \ R1= length of FNAME \ setup to copy VDP FNAME ->namebuf to '.' character R1 R3 MOVB, \ DUP length byte to R3 R3 08 SRL, \ swap the byte to other side R4 SETO, \ R4 = -1 R2 NAMBUF LI, \ R2 is ^namebuf BEGIN, R0 INC, \ point to next fname VDP address R4 INC, \ counter starts at 0 R4 R3 CMP, \ is counter = fnamelength @@1 JEQ, \ if true goto @@1: R0 VDPWA, \ set VDP address VDPRD @@ R1 MOVB, \ read next VDP char from fname R1 *R2+ MOVB, \ copy to namebuf & inc pointer R1 PERIOD @@ CMPB, \ is it a '.' EQ UNTIL, \ until '.' found 34 bytes!!! @@1: R4 R4 MOV, \ test R4(device name length)=0 @@6 JEQ, \ if so, goto ERROR6 R4 07 CMPI, \ is dev name length>7 @@8 JGT, \ if so, goto @@8 (ERROR6) 83D0 @@ CLR, \ erase magic CRU addr. holder R4 8354 @@ MOV, \ put length in magic address R4 INC, \ +1 points to '.' character R4 8356 @@ ADD, \ add offset to PAB address (makes "real PAB") \ ==== GPL WORKSPACE ==== 83E0 LWPI, \ SROM (search ROM device list) R1 CLR, \ MAGIC GPL REGISTER=0 H2000 @@ CYC1 @@ MOV, \ init the CYC1 variable ?? R12 1000 LI, \ init CRU base to 1000 @@A JMP, @@9: R12 1000 LI, \ init CRU address H1300 @@ CYC1 @@ MOV, \ @@A: BEGIN, \ scan for I/O cards R12 R12 MOV, NE IF, \ if card address<>0 00 SBZ, \ turn off card ENDIF, R12 0100 ADDI, \ advance CRU to next card 83D0 @@ CLR, \ erase magic addres R12 2000 CMPI, \ @@9 JEQ, \ Scan ROM R12 CYC1 @@ CMP, @@5 JEQ, \ no more cards. goto ERROR5 \ card activation... R12 83D0 @@ MOV, \ save card CRU in magic address 00 SBO, \ turn on the card R2 4000 LI, \ ROM start addr -> R2 *R2 HEXAA @@ CMPB, \ test for card present EQ UNTIL, \ loop until card is found DREG(5) @@ R2 ADD, \ add '8'+4000= >4008 DSR ROM list @@9 JMP, @@3: \ scan ROM linked list for code address BEGIN, BEGIN, 83D2 @@ R2 MOV, \ start of ROM device list -> R2 00 SBO, \ turn card on @@9: *R2 R2 MOV, \ Fetch next link @@A JEQ, \ if link=0 goto @@A (NEXT CARD) R2 83D2 @@ MOV, \ save link address in magic address R2 INCT, \ R2 = code pointer *R2+ R9 MOV, \ fetch code address ->R9 8355 @@ R5 MOVB, \ dev length->R5 @@4 JEQ, \ if 0 we have a string match R5 *R2+ CMPB, \ EQ UNTIL, \ find dev string match R5 08 SRL, \ shift length byte R6 NAMBUF LI, \ R6 holds ^nambuf BEGIN, *R6+ *R2+ CMPB, \ compare namebuf to ROM string @@3 JNE, \ if mismatch goto @@3 R5 DEC, \ dec the counter register EQ UNTIL, @@4: \ DJUMP4 run DSR code R1 INC, \ count entries into the DSR ? *R9 BL, \ call the DSR code AGAIN, \ try next card \ -- DSR returns here if we are done -- 00 SBZ, \ Turn off the card DREGS LWPI, \ ==== DSR Workspace ==== R9 VDPWA, \ set vdp address VDPRD @@ R1 MOVB, \ read error value to DREGS R1 R1 0D SRL, \ shift error to correct range @@7 JNE, \ if error<>0 goto @@7 RTWP, \ else return to Forth workspace \ error condition handlers @@5: DREGS LWPI, @@6: \ dev. name too long @@8: R1 SETO, \ dev. name not found: code = -1 @@7: R1 [TOS] MOV, \ put error code in Forth HEX20 @@ R15 SOCB, \ set EQ flag = 1 RTWP, \ ====== DSR LINK ENDS====== \ the vector for BLWP l: DLNK DREGS T, DSR1 T, CODE: DSRLNK ( -- ior) TOS PUSH, \ space for error code on Forth stack TOS CLR, 0 LIMI, \ critical that we disable interrupts here. DLNK @@ BLWP, 8 DATA, 2 LIMI, NEXT, END-CODE Edited November 16, 2018 by TheBF Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 the address of the PAB filename length byte is stored at >8356 Can someone explain this to me in relation to what I'm using as my "filename length" byte? I have the following: #COUNT BSS 16 This keeps track of the length of my filename that a user would create earlier in the process. How would I store that correctly to >8356? Could I just simply do: Mov @COUNT, @>8356 But I thought>8356 needs an address, not the actual number length of my filename? Just trying to figure this. Thx Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 29, 2020 Share Posted October 29, 2020 36 minutes ago, GDMike said: the address of the PAB filename length byte is stored at >8356 Can someone explain this to me in relation to what I'm using as my "filename length" byte? I have the following: #COUNT BSS 16 This keeps track of the length of my filename that a user would create earlier in the process. How would I store that correctly to >8356? Could I just simply do: Mov @COUNT, @>8356 But I thought>8356 needs an address, not the actual number length of my filename? PABs are stored in VRAM. The first 10 bytes are fixed and contain I/O information for the DSR. The last of these bytes, byte 9, is the filename length byte. The rest of the PAB is for the filename, including the device name, say DSK1. If a file is named SNP001 on DSK1, PAB byte 9 would be 11 followed by DSK1.SNP001. The VRAM address of the PAB’s filename length byte is what you must store at >8356, not whatever copy of it you may be storing in CPU RAM (CRAM). Whatever PAB information you track in CRAM must eventually get copied to the PAB before calling DSRLNK. Good discussions of file handling are in Section 18 of the E/A Manual and Chapter 8 of the fbForth 2.0 Manual. If you store your PAB in VRAM at >0500, the address of the filename length byte is >0500 + 9 = >0509, which is what you would store at >8356 before calling DSRLNK. ...lee 3 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted October 29, 2020 Share Posted October 29, 2020 (edited) Yes, in a PM, I suggested... Then MOVB @COUNT,@FSPAB+9, should work. I was a little confused at that point in our dialog. That should be... MOV @COUNT,@PBAD+9 However, in your code that I was reviewing, you had not yet copied your PAB to VDPRAM! But that must be done before you execute the DSR. EDIT: OK, above is still wrong ...correcting, testing,. OK... I'm back on track... The original example... Then MOVB @COUNT,@FSPAB+9, should work. ...is correct, but, for a different issue ...namely, how to move the length byte from @COUNT into the "PAB data", located in CPURAM. Quote Could I just simply do: Mov @COUNT, @>8356 No, this would move the "number length" into >8356. To move the address of where that length byte is in VDPRAM, use: LI R6,PBAD+9 MOV R6,POINTR But, you must also move the PAB data into VDPRAM... * DO THE WRITE! LI R0,PBAD LI R1,FSPAB LI R2,20 BLWP @VMBW LI R2,20, is from the example given in the Molesworth book Pg. 82('DSK1.FILE '), the example shows a trailing space, perhaps for a single digit to be appended, but as Lee mentioned, "The first 10 bytes are fixed and contain I/O information for the DSR.", If your DEVICE+FILENAME might be longer, you should increase the value given to R2 accordingly. It should be permissible to use the max. length you wish to allow/device can handle, rather than the exact length your user provides at each individual entry. The length does need to be specific in byte 9, of the PAB at each and every call of the DSR though. Ahh, back to my own personal drudgery! Edited October 29, 2020 by HOME AUTOMATION Spellin' ...correcting,,, Ahh. 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 Yes, and I'm doubling back over again because I'm trying to understand it. I see where your coming from now, as it's starting to make sense. Lee has it here: in fb manual, section#8 "Access to File I/O Using TI-99/4A Device Service Routines" Documented real nice. I might actually learn something now. TBD... 1 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted October 29, 2020 Share Posted October 29, 2020 New PM sent. 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 I'm going to start fresh in the morning I'm looking over the vram mapping which is, I've been having a hard time trying to find it, but I have some info on it now. Because you really have to follow it to get the DSR link right. But I'll start back on this in the morning. I understand how the PAB works I just don't understand the addressing involved and how much space those addresses need. So I'll pick it up in the morning 1 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted October 29, 2020 Share Posted October 29, 2020 (edited) I added "a few little corrections" to post: #159 Edited October 29, 2020 by HOME AUTOMATION " Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted October 29, 2020 Share Posted October 29, 2020 7 hours ago, GDMike said: #COUNT BSS 16 Since the filename length is specified as a single byte, shouldn't COUNT BSS 1, suffice? In your PM, you seem to offer differing accounts of how COUNT is used. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 29, 2020 Author Share Posted October 29, 2020 5 hours ago, HOME AUTOMATION said: Since the filename length is specified as a single byte, shouldn't COUNT BSS 1, suffice? In your PM, you seem to offer differing accounts of how COUNT is used. To me it depends on how one sees the world. In the E/A Manual the count and the string are understood to be separate pieces of data. This is an Assembly Language view of the computer IMHO. One can look at the count and the text as part of something called a byte counted string, where the 1st byte is the length. So GDMike's BSS 16 gives you room for this entire data structure. Of course one has to remember in your code that this label is pointing one these "counted strings" but it's not a big thing to remember once you commit to the concept. 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 5 hours ago, HOME AUTOMATION said: Since the filename length is specified as a single byte, shouldn't COUNT BSS 1, suffice? In your PM, you seem to offer differing accounts of how COUNT is used. Ok? I had something in mind at the time and it made sense, but I don't see Why I can't make , COUNT BSS 1 Let's roll with that, since I can't talk myself out of it. Lol Let's move on... I've got this understood. Thx everyone Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 12 hours ago, HOME AUTOMATION said: LI R0,PBAD LI R1,FSPAB LI R2,20 BLWP @VMBW First piece I've got understood Quote Link to comment Share on other sites More sharing options...
+9640News Posted October 29, 2020 Share Posted October 29, 2020 5 hours ago, HOME AUTOMATION said: Since the filename length is specified as a single byte, shouldn't COUNT BSS 1, suffice? In your PM, you seem to offer differing accounts of how COUNT is used. Also keep in mind that the following are the same as far as length. I'm not entirely sure, but I think the use of the BSS statement does not dictate the byte is automatically a >00 byte by all assemblers while the BYTE statement does. COUNT BSS 1 COUNT BYTE 0 If you have no other single byte labels before or after, then you will have actually used two bytes of memory space as all instructions are on even byte boundaries. Myself, I always add an EVEN statement after the use of odd number BSS's or BYTE statements. Beery 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 29, 2020 Share Posted October 29, 2020 It is important that a byte counted string have the count (length) byte be contiguous with the string it is counting, so it might be best to use a combination of BYTE and TEXT directives: COUNT BYTE 0 FNAME TEXT ' ' EVEN Copying to the PAB in VRAM at VPAB, say, is easily done by LI R0,VPAB+9 LI R1,COUNT LI R2 16 BLWP @VMBW because FNAME starts immediately after the COUNT byte. ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 (edited) 27 minutes ago, Lee Stewart said: #169 Ok, I also have a label that contains a user defined filename, that could contain this, DSK4.FILENAME FLNM BSS 16 Edited October 29, 2020 by GDMike 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 (edited) Ok. My next question where is the PAB address supposed to be is it designated to one location in vram. Ok. I see this excerpt. And I already have another PAB placed at >7D0. So I've got to place my "FSPAB" somewhere before>7D0. Edited October 29, 2020 by GDMike Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 (edited) Like this. FSPAB EQU >79E And, correct. I'm using TEXT mode. ******************** code * DO THE WRITE! LI R0,PBAD LI R1,FSPAB LI R2,20 BLWP @VMBW IM SUPPOSED TO DO A BL @ DSR FROM HERE WHICH IS NEED TO CREATE. SBUFF EQU >1000 * BUFFER ADDRESS PBAD EQU >79E * PAB ADDRESS FSPAB DATA >0012,SBUFF,>8000,>0000,>0000 * OP DV 128 COUNT BYTE 0 FLNM BSS 16 STATUS EQU >837C POINT EQU >8356 READP BYTE >02 CLOSEP BYTE >01 EOFP DATA 0 ERRM TEXT '* I/O ERROR * ' CPUBF BSS 80 LENP BSS 2 Edited October 29, 2020 by GDMike Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 (edited) If everything in the last post is workable, ill move on to hopefully create the DSR routine. Im guessing, the DSR section will be called to do the actual data move from CPU ram, where MY SCREEN DATA is stored, and find its way into VRAM and then onto DISK. Edited October 29, 2020 by GDMike Quote Link to comment Share on other sites More sharing options...
apersson850 Posted October 29, 2020 Share Posted October 29, 2020 Where you can position you PAB in VDP RAM does of course depend on your runtime environment. If you make support routines running under Extended BASIC you have one scenario. If you are using Pascal, Forth or whatever, you have different scenarios. When you run a pure assembly program, you define the scenario. There are assumptions when your program starts, depending on if it's loaded by Editor/Assembler module or something else, but you can change them as you like. The BYTE and DATA directives generate code with specific data. BYTE 27 BYTE 32 DATA 15364 will generate four bytes of code. BSS 4 as well as BES 4 will reserve space for four bytes of data, but no specific value will be loaded. Normally, the loader program will just skip these bytes, and start loading values four bytes further ahead. Thus COUNT BSS 16 will reserve the same amount of space as COUNT BYTE 0 BSS 15 but in the second case, you are certain that COUNT is set to zero when the program starts. 1 Quote Link to comment Share on other sites More sharing options...
GDMike Posted October 29, 2020 Share Posted October 29, 2020 (edited) now, ive got to create the DSR routine. Ive started this with, following the example, from "introduction to assembly language" page 84 DSR LI R6,FSPAB+9 this is supposed to look at my FILENAME that the user placed into FLNM?? i hope and pray!! then I move R6 @ point! MOV R6,POINT * >8356 Edited October 29, 2020 by GDMike 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.