Jump to content
IGNORED

Command Mode Error Codes vs Run Mode Error Codes for I/O Errors


4Andy

Recommended Posts

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 by 4Andy
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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 by FarmerPotato
  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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]               ***********************************************************
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by 4Andy
  • Like 1
Link to comment
Share on other sites

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 by RXB
Link to comment
Share on other sites

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 by Casey
Link to comment
Share on other sites

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 by senior_falcon
  • Like 2
Link to comment
Share on other sites

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

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...