4Andy Posted May 11, 2018 Share Posted May 11, 2018 (edited) Hi, does anyone know if it is possible to get the same Error Code that the Command Mode issues for an I/O error, but from within an Extended Basic program? There seems to be two error codes returned for the same thing, depending on whether you are in Command Mode or Run Mode. For example: DELETE "XXXX.XXXX" if you execute the above in Run Mode, CALL ERR() returns: error = 130, file = 0, and whichever line number that the statement occurred in. However, if you execute the same command in Command Mode, you get a potentially more useful code of 70. 7 = error in DELETE routine, 0 = BAD DEVICE NAME. Is there some method of retrieving this code, for example is there a reliable location I can peek? I'm happy to use PEEKV, but I want to avoid an Assembly routine if possible as I want this to be Assembly free. I am trying to write some decent error handling where the messages are clear and helpful and any unhandled errors will allow a data save, so that no data is lost. Finding out if a Save failed due to the disk just being write protected would be more helpful than just displaying "I/O ERROR, GUV'NOR". Failing that, I will have to use precious RAM to set up some variables to define context, but it still doesn't help with the Write Protection issue. :-/ Andy. Edited May 11, 2018 by 4Andy Quote Link to comment Share on other sites More sharing options...
RXB Posted May 11, 2018 Share Posted May 11, 2018 Ok they are the same exact error. Let me show you the code: [0612] * File Error [0613] 62A6 09,A9,8F MSG130 BYTE >09,>A9,>8F,>AF,>80,>A5,>D2,>D2,>CF,>D2 62A9 AF,80,A5 62AC D2,D2,CF 62AF D2 [0614] * I/O Error [0615] 62B0 14,B3,D5 MSG135 BYTE >14,>B3,>D5,>C2,>D0,>D2,>CF,>C7,>D2,>C1,>CD,>80 62B3 C2,D0,D2 62B6 CF,C7,D2 62B9 C1,CD,80 [2019] * [2020] * Error turned on. Now build the error entry [2021] * [2022] 6DBF 06,76,7F G6DBF CALL CLEAN Clean up the stack [2023] 6DC2 BD,4A,56 DST @FAC12,@FAC Put in error & severity [2024] 6DC5 BE,4C,69 ST >69,@FAC2 Error stack ID [2025] 6DC8 D7,54,62 DCEQ MSG130,@FAC10 If I/O error 6DCB A6 [2026] 6DCC 4D,D6 BR G6DD6 [2027] 6DCE BC,4D,E0 ST V@2(@PABPTR),@FAC3 * Put in LUNO # 6DD1 02,04 [2028] 6DD3 B6,4B,80 OR >80,@FAC1 And indicate an I/O error [2029] 6DD6 BD,50,2E G6DD6 DST @EXTRAM,@FAC6 Save line pointer [2030] 6DD9 BD,4E,1E DST @SMTSRT,@FAC4 Save pointer to beginning of [2031] * statement [2032] 6DDC BD,5C,6E DST @VSPTR,@ARG Must check for room on stack [2033] 6DDF A3,5C,00 DADD 24,@ARG Need 24 to help out VPUSH 6DE2 18 [2034] 6DE3 C5,1A,5C DCH @ARG,@STREND If not room [2035] 6DE6 6D,FD BS G6DFD [2036] 6DE8 06,6E,0E CALL ERPRNT Put out the message anyway [2037] 6DEB BF,54,61 DST MSG39,@FAC10 Memory full message 6DEE 1C [2038] 6DEF 86,44 CLR @PRGFLG Don't print a line # [2039] 6DF1 06,6E,0E CALL ERPRNT Print it too [2040] 6DF4 31,00,08 MOVE 8,G@MSGERR,V@NLNADD-18 6DF7 A2,D0,60 6DFA 38 [2041] 6DFB 4D,47 BR ERRZZ5 And give up [2042] 6DFD 0F,77 G6DFD XML VPUSH Push the error entry [2043] 6DFF 87,2E DCLR @EXTRAM Clear on-error entry [2044] 6E01 C1,2E,A3 DEX V@ERRLN,@EXTRAM Set line pointer & clear on-e 6E04 8A [2045] 6E05 06,80,2C CALL GRSUB2 Read the line text pointer VD [2046] * ERAM (use GREAD1) or VDP [2047] 6E08 2E BYTE EXTRAM * @EXTRAM : Source address [2048] * in ERAM/VDP [2049] 6E09 BD,2C,58 DST @EEE1,@PGMPTR Put the result in @PGMPTR [2050] 6E0C 0F,81 XML CONTIN And go to the line [2051] *********************************************************** [2052] * ERPRNT - Print an error or warning message 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0039 EDIT-359 [2053] * [2054] * ERPRNT - Entry point for ERROR [2055] * ERPNT5 - Entry point for WARNING [2056] *********************************************************** [2057] 6E0E 06,60,1C ERPRNT CALL G601C Load the character table [2058] 6E11 0F,83 XML SCROLL Scroll the screen [2059] 6E13 BE,A2,E2 ST >2A+OFFSET,V@NLNADD Put the * in 6E16 8A [2060] 6E17 BF,20,02 DST NLNADD+2,@VARW Set up for the message 6E1A E4 [2061] 6E1B 86,74 ERPNT5 CLR @KEYBD Enable main console [2062] 6E1D 33,00,01 MOVE 1,G@0(@FAC10),@ARG1 Get message length 6E20 5D,00,00 6E23 54 [2063] 6E24 86,5C CLR @ARG [2064] 6E26 32,5C,B0 MOVE @ARG,G@1(@FAC10),V*VARW Display 6E29 20,00,01 6E2C 54 [2065] 6E2D A1,20,5C DADD @ARG,@VARW Start location for " IN " [2066] 6E30 D7,54,62 DCEQ MSG130,@FAC10 "* I/O ERROR [xx]xy" 6E33 A6 [2067] 6E34 4E,4D BR G6E4D [2068] 6E36 91,20 DINC @VARW Update for one space [2069] * separation [2070] 6E38 BC,5F,E0 ST V@>04(@PABPTR),@ARG3 * Create high order resu 6E3B 04,04 [2071] 6E3D 86,5E CLR @ARG2 Only display high order decim [2072] 6E3F 06,6F,BA CALL DISO Display this number [2073] 6E42 BC,5F,E0 ST V@>05(@PABPTR),@ARG3 * Get low order result 6E45 05,04 [2074] 6E47 E6,5F,05 SRL 5,@ARG3 Remove mose identification bi [2075] 6E4A 06,6F,BA CALL DISO Output the number in decimal [2076] 6E4D D7,54,60 G6E4D DCEQ MSGFST,@FAC10 * Ready * (* RXB *) 6E50 40 [2077] 6E51 6E,79 BS G6E79 [2078] 6E53 06,00,36 CALL TONE2 Wake up the idiot!!!! [2079] 6E56 8E,44 CZ @PRGFLG If program, print line # [2080] 6E58 6E,79 BS G6E79 [2081] 6E5A C7,20,02 DCH >02F6,@VARW It will pass EOL 6E5D F6 [2082] 6E5E 4E,66 BR G6E66 [2083] 6E60 0F,83 XML SCROLL Display on next line [2084] 6E62 BF,20,02 DST NLNADD+1,@VARW Indent for the "IN" 6E65 E3 [2085] 6E66 BF,E0,01 G6E66 DST >C9CE,V@1(@VARW) * Put in the "in" 6E69 20,C9,CE [2086] 6E6C A3,20,00 DADD 4,@VARW Display location for line 6E6F 04 [2087] 6E70 BC,76,42 ST @CHAT,@EXPZ ASC destroys CHAT [2088] 6E73 06,A0,0A CALL ASC DISPLAY THE LINE # [2089] 6E76 BC,42,76 ST @EXPZ,@CHAT Restore CHAT [2090] 6E79 0F,83 G6E79 XML SCROLL [2091] 6E7B 00 RTN [2092] *********************************************************** The Program mode error is more concerned with the line number that created the error then the actual error. Now every error is pushed onto the VDP STACK thus if you peek the VDP STACK the error number will be there. If you want to avoid errors use ON ERR line-number to avoid the report of the error. Use CALL ERR(W,X,Y,Z) per page 83 of the XB manual to handle your errors. 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted May 11, 2018 Share Posted May 11, 2018 (edited) Since Extended Basic just sets error to 130 meaning I/O ERROR, I think you have to retrieve the error byte from the PAB in VDP. I've never done this from Basic, but here is a beginning: Theory This would apply if the file were still open (no help with a DELETE statement!) Start with the PAB list. Get the 2 bytes at CPU address >833C (Somebody shoot me if I'm wrong. I'm just reading the docs for the first time since Craig Miller covered XB VDP memory in detail in Smart Programmer.) http://www.unige.ch/medecine/nouspikel/ti99/vdpram.htm That gives you a VDP address to start looking at. The VDP memory contains a linked list: 2 bytes: next PAB's VDP address or 0 1 byte: file number 1 byte: hmm 10 bytes: PAB with length byte at byte 9 N bytes: filename If the IO error was for a file # that is still open, there would be a PAB entry for it. Assuming you had CALL PEEKV.. (probably you get your own and write CALL LINK("PEEKV", A,B,C,D ) etc CALL PEEK(-31940, A, B) V = A*256+B CALL PEEKV(V, A, B) V2 = A*256+B CALL PEEKV(V+2, FILENUM) Inside the PAB structure, byte 0 is the operaton and byte 1 contains the error code (upper 3 bits). http://www.unige.ch/medecine/nouspikel/ti99/headers.htm#PAB CALL PEEKV(V+4, A, B) E = A*10+INT(B/32) E would be your I/O Error code. I don't think there's anything in that table for a DELETE statement that doesn't keep an open file, so no juice. But I think this is the answer for a file that is still open. TEST So I tried this 10 ON ERROR 50 20 DELETE "DSK2.HHHH" 30 END 50 CALL ERR(A,B) 60 PRINT A,B 70 GOTO 70 Without the ON ERROR I get I/O ERROR 73. Poking around at runtime, I find a likely PAB at VDP >37A9. It starts with 07 60 which is the opcode DELETE and error bits 011 or 3. The length byte is at >37B2 Size of PAB is 10 + 9 for the filename which makes the next VDP address >37BC I looked for anything in CPU RAM pointing to those addresses. Nope. I guess though that this is inside the String Space.. Basic made a temporary string allocation and then freed it? I'm not sure. Now I want to know the answers! Edited May 11, 2018 by FarmerPotato 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted May 12, 2018 Share Posted May 12, 2018 Ok let me explain this again as I may have not been clear about the GPL code I posted. ERROR 73 and ERROR 130 are BOTH I/O ERROR How you get a different response is due to CALL ERR being used or not. After all 73 I/O Error is exactly the same error as 130 they just differ in how they are reported, again due to if CALL ERR is used or not. See CALL ERR needs to find and load SEVERITY and is not needed if CALL ERR is not used. Quote Link to comment Share on other sites More sharing options...
Casey Posted May 12, 2018 Share Posted May 12, 2018 I think what Andy wants is to interrogate the digits of the I/O ERROR xx that occurred and take action depending on the error code - if I understood correctly. Take this short example: 10 ON ERROR 50 20 DELETE "DSK2.AAA" 30 PRINT A,B,C,D 40 END 50 CALL ERR(A,B,C,D)::RETURN NEXT If you run this with no disk in DSK2, the results of the CALL ERR are 130,0,9,20 Delete line 10 and you get I/O ERROR 76 Now put line 10 back in and change line 20 to: 20 OPEN #1:"DSK1.AAA",INPUT,DISPLAY,FIXED Assuming you don't have a file named AAA on DSK1, the results of CALL ERR are 130,1,9,20 Delete line 20 and you get I/O ERROR 02 CALL ERR doesn't tell you anything differently in each of these cases except that file #1 caused the error in line 20 instead of no file. But if you could know the 76 or the 02, you could tell the user something useful rather than just stop the program or say "An error occurred". You could tell the user the file was not found on the disk, or to put a disk in the disk drive. That number returned by I/O ERROR must be stored somewhere when the error message is prepared. Quote Link to comment Share on other sites More sharing options...
RXB Posted May 12, 2018 Share Posted May 12, 2018 This is from the XB GPL source: [1934] *********************************************************** [1935] * ERRZZ - Sets up an error stack entry based upon the [1936] * information passed to it by the caller and what it can [1937] * gather from the error table. It then either prints the [1938] * error message and aborts or goes to the line specified by [1939] * a previously executed ON ERROR statement. The stack enrry [1940] * looks like: [1941] * --------------------------------------------------------- [1942] * | Error code | Severity | >69 | Luno # | EXTRAM | PGMPTR [1943] * | ^ | ^ | ^ | ^ | ^ | ^ [1944] * | FAC | FAC1 | FAC2| FAC3 | FAC4 | FAC6 [1945] *---------------------------------------------------------- [1946] * ERROR CODE - the error number [1947] * SEVERITY - Severity of the error [1948] * 1 - Warning [1949] * 5 - Possibly recoverable [1950] * 9 - Fatal, unrecoverable [1951] * >69 ERROR STACK ENTRY ID [1952] * LUNO # - Luno # if file error or -1 if non-file error [1953] * EXTRAM, PGMPTR - Information to indicate the line # of [1954] * the error [1955] *********************************************************** Quote Link to comment Share on other sites More sharing options...
Casey Posted May 12, 2018 Share Posted May 12, 2018 It seems that it isn't possible then to get the 2 digit I/O ERROR code then via CALL ERR. That's too bad - feels like an oversight by the programmers. Not all I/O ERRORs are fatal to a program so it would be nice to know that code. It's interesting also that they made provisions for different values for the error severity but the only one that was ever used was 9. They kind of fixed this on the CC-40. Quote Link to comment Share on other sites More sharing options...
4Andy Posted May 12, 2018 Author Share Posted May 12, 2018 (edited) Hi, sorry for the delay. Thank you for all your responses and for taking the time to respond with such detailed suggestions. I don't think I asked my question clearly enough, but Casey is correct. I am trying to get as much information as possible about the I/O error, which I've already trapped (with ON ERROR), so that the program can give remedial advice. I don't think it's enough for the program to say "I/O error", as it could mean anything. I know 130 and 70 are the same error, but the 70 version has more information that I could use to improve the error handling and advice greatly. Presumably the VDP Stack that RXB refers to, is in VDP ( :-) ) and I'd also forgotten that the standard Extended Basic doesn't have POKEV and PEEKV, so I can't get at that from Extended Basic without Assembly as indicated above and I'm trying to keep the error handling Assembly free. :-/ . Is the FAC that RXB refers to the same FAC in the PAD? Although, it's unlikely that value will still be available by the time my code is executed, due to re-use. Is there something in PAD, that I can use with CALL PEEK()? I've looked at the content following an error in Classic99 and cannot see anything, but that doesn't mean that nothing is there, as I don't know it well enough to know what I'm looking for. Edited May 12, 2018 by 4Andy 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted May 12, 2018 Share Posted May 12, 2018 (edited) It seems that it isn't possible then to get the 2 digit I/O ERROR code then via CALL ERR. That's too bad - feels like an oversight by the programmers. Not all I/O ERRORs are fatal to a program so it would be nice to know that code. It's interesting also that they made provisions for different values for the error severity but the only one that was ever used was 9. They kind of fixed this on the CC-40. LOL the XB cart compared to TI Basic is laughably different. TI Basic does not have 12K of Assembly ROM! TI Basic does not support half the error reports that XB does, do you see a CALL ERR in TI Basic? Do you see ON ERROR line-numbrer in TI Basic? Most of the problems in XB Error reports are a direct result of staying compatible with TI Basic! If you want to lay blame you can directly put that on TI Basic and the minimalist approach it took to errors. XB tries to stay as backwards compatiable with TI Basic Error reports as possible, but the entire problem XB has with errors is directly the crap version of TI Basic approach. Edited May 12, 2018 by RXB Quote Link to comment Share on other sites More sharing options...
Casey Posted May 12, 2018 Share Posted May 12, 2018 (edited) If I did my math right, I tried this version of the program example above: 10 ON ERROR 50 20 OPEN #1:"DSK1.AAA",INPUT,DISPLAY,FIXED 30 PRINT A,B,C,D 40 END 50 CALL PEEK(-31926,E)::PRINT E::CALL ERR(A,B,C,D)::RETURN NEXT I never get anything but 0 in E, and I think I have the right address for FAC (>834A = 33610, 33610-65536 = -31926) Edited May 12, 2018 by Casey Quote Link to comment Share on other sites More sharing options...
4Andy Posted May 12, 2018 Author Share Posted May 12, 2018 Pants. That's disappointing. Cheers guys, but if any of you have any flashes of inspiration, please let me know! Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 13, 2018 Share Posted May 13, 2018 (edited) When there is a file error, the first 3 bits in byte 1 of the PAB contain an error code from 0 to 7. That could be useful, but only if you can find the PAB. I experimented a bit with this using Classic99's debugger. When you OPEN a file, first a garbage collection is performed and the strings are moved as necessary so that the PAB can be just above them in the VDP. After the garbage collection, >8318 in the scratchpad contains an address that points to the beginning of the string space. Add 6 to that address and it will point to byte 1 of the PAB. Peek that byte and divide by 32, then take the INT to get the error code. There is no warranty with this; it seems to work with a single disk file. I don't know how you would deal with it if there were more than one disk file opened. Remember that there is no PEEKV in XB, so you'd have to either use an assembly subprogram to peek the value or else RXB which has PEEKV. The code below was tested in RXB. It returns an error code of 0 with the misspelling of DSK. I get an error code of 2 if the file name is good but the file type is wrong. 10 ON ERROR 100 20 OPEN #1:"DSJ1.APERTURE.OBJ" 100 CALL PEEK(-31976,A,B):: CALL PEEKV(A*256+B+6,EC):: PRINT INT(EC/32) Error codes from page 299 of the EA manual 0 Bad device name 1 Device is write protected 2 Bad open attribute.... 3 Illegal operation... 4 Out of table or buffer space on the device 5 Attempt to read past the end of the file... 6 Device error 7 File error.... (edit) Looks like FarmerPotato covered a lot of this in post #3. Also, PAB byte 0 can be queried and the status byte which is R8. Pages 297-299 of the E/A manual have more info on this. (edit2) XB256 has VREAD which can read a string from VDP memory. You could read the entire PAB with CALL LINK("VREAD",A*256+B+5,10,PAB$) Then you would use B1=ASC(SEG$(PAB$,2,1)) to extract byte 1 and likewise for bytes 0 and 8 Edited May 13, 2018 by senior_falcon 2 Quote Link to comment Share on other sites More sharing options...
4Andy Posted May 13, 2018 Author Share Posted May 13, 2018 Thank you, again. :-) I guess my ASM progs will be ok, but my XB ones will have to use context, even if it may not be 100% accurate. It's frustrating. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 14, 2018 Share Posted May 14, 2018 I guess my ASM progs will be ok, but my XB ones will have to use context, even if it may not be 100% accurate. It's frustrating. As far as I know, this method gives an XB program access to the same error information available to an assembly program. But only if you use RXB, XB256, or a custom PEEKV routine 1 Quote Link to comment Share on other sites More sharing options...
4Andy Posted May 14, 2018 Author Share Posted May 14, 2018 I understand. I was trying to create something for standard XB that may or may not have 32K available. I'll be able to use it for my own progs though, so thanks again for this. 1 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.