TRS-80 DOS – TRSDOS v1.3 – SYS10/SYS Disassembled

General:

SYS10/SYS handles DISPLAY DIR ($DSPDIR) and BASIC Error Messages.



Disassembly:

 
ORG 4E00H
“START”
4E00
AND 0F0H
On entry, every overlay has a routine request in Register A, which is routinely masked to retain only the high nybble. MASK the value of Register A against 0F0H (1111 0000) to leaving only bits 7, 6, 5, 4 active.
4E02
CP 90H
Compare the value held in Register A against 90H to see if this was a request to display an error message. If Register A equals 90H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E04
JP Z,DOERR
     [4EF0H]
If the entry call was 90H, then the Z FLAG (Zero) will have been set, meaning that this Overlay was involked to display an error; JUMP to 4EF0H to handle it.
“DODIR”
4E07
XOR A
Set Register A to ZERO and clear all Flags so that we can set the overlay flag to indicate that SYS06/SYS is NOT in memory.
4E08
LD (442BH),A
Store the 0 held in Register A into memory location 442BH.
4E0B
LD A,(4271H)
Fetch the drive number from memory location 4271H and store it into Register A.
4E0E
AND 03H
The first two bits of Register A hold the drive number, so MASK the value of Register A against 03H to keep only bits 1-0.
“DIRGET”
4E10
LD (DRIVE),A
Store the drive number (held in Register A) into memory location 4EDAH.
4E13
CALL 01C9H
     [01C9H]
Clear the screen via a GOSUB to 01C9H.
NOTE: 01C9H is the Model III ROM routine to to CLEAR THE SCREEN and RETurn.
4E16
LD A,0EH
Let Register A equal 0EH which is the ASCII code for CURSOR ON.
4E18
CALL 0033H
     [0033H]
Turn the cursor on via a GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4E1B
LD A,(DRIVE)
Fetch the drive number (held in memory location 4EDAH) and store it into Register A.
4E1E
LD B,A
Copy the drive number from Register A into Register B.
4E1F
LD A,(4413H)
Fetch the highest drive number in the system from memory location 4413H and store it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
4E22
CP B
Make sure we actually have the drive by comparing the highest drive number in the system(held in Register A) against the drive number supplied (held in Register B). If if the maximum drive number (A) >= the requested drive number (B), the NO CARRY FLAG will be set.
4E23
JR NC,DIRLOP
      [4E2AH]
If the drive number is valid, then the NC FLAG (No Carry) will have been set, so continue via JUMP to 4E2AH.
4E25
LD A,0C2H
Let Register A equal 0C2H to set up for a DRIVE NOT IN SYSTEM error.
4E27
JP 4409H
   [4409H]
JUMP to 4409H, which is the SYS00/SYS routine to process DOS errors.

4E2AH – Read the directory track into a Buffer in RAM.

“DIRLOP”
4E2A
LD A,(DRIVE)
Fetch the drive number (held in memory location 4EDAH) and store it into Register A.
4E2D
PUSH AF
Save the drive number to the top of the stack.
4E2E
CALL TRKGET
     [4B3EH]
GOSUB to 4B3EH.
NOTE: 4B3EH is the SYS00/SYS routine to identify the track number of the directory. Routine exits with the director track number in Register D.
4E31
LD A,D
Copy the directory track number for the given drive (held in Register D) into Register A.
4E32
LD (SAVTRK),A
Store the directory track number for the given drive into memory location 4E56H, which is in the middle of a LD D,0 OPCODE.
4E35
POP AF
Restore the drive number from the top of the stack.
4E36
ADD A,30H
LET Register A = Register A + 30H. Note: Adding 30H to from Register A will convert decimal number 0-9 into its ASCII equivalent (i.e., 6 + 30H = 36H, which, in ASCII, is 6.
4E38
LD (DRV),A
Store the ASCII rendition of the drive number (held in Register A) into the middle of the DRIVE MESSAGE at memory location 4EE3H.
4E3B
LD A,01H
Let Register A equal 01H.
4E3D
LD (NUM),A
Store a 1 into memory location 4EEFH as the starter value for how many filenames have been displayed on the current screen line.
4E40
LD HL,DRVMSG
Let Register Pair HL equal 4EDCH to point to the drive number message.
4E43
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
“DIRLO1”
4E46
LD A,02H
Let Register A equal 02H to point to Sector 2.
4E48
LD (S10SEC),A
Store the sector number (held in Register A) into memory location 4EEEH.
“DIRLO2”
4E4B
LD HL,S10SEC
Let Register Pair HL equal to the track pointed to at 4EEEH.
4E4E
LD A,(HL)
Fetch the sector number (held in the memory location pointed to by Register Pair HL) and store it into Register A.
4E4F
INC (HL)
INCrement the value stored in the memory location pointed to by Register Pair HL by 1 to point to the next sector.
4E50
LD E,A
Copy the sector number into Register E to prepare for the next call.
4E51
LD A,(DRIVE)
Fetch the current drive number (held in memory location 4EDAH) and store it into Register A.
4E54
LD C,A
Copy the contents of Register A into Register C for the CALL.
4E55
LD D,(**SAVTRK**)
Let Register D equal the directory track (placed into 4E56H at 4E32H).
4E57
LD HL,4300H
Let Register Pair HL equal 4300H.
NOTE: 4300H is a memory buffer (referred to as Memory Buffer 1) where diskette contents are stored in RAM.
NOTE: 4300H is the storage location for the 256 Byte Storage Area for Disk I/O.
4E5A
CALL XREAD
     [4675H]
Read the directory track into the buffer via a GOSUB to 4675H.
4E5D
JR Z,NOERR
     [4E64H]
If the Z FLAG (Zero) has been set then there was no error, so JUMP to 4E64H.
4E5F
OR 0C0H
If we’re here then there was an error reading that track. OR Register A against 0C0H (1100 0000) to prepare to set error codes to detailed messages instead of just numbers.
4E61
JP ERROR
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

4E64H – Process the directory track now in RAM to find the filename.

“NOERR”
4E64
LD HL,4300H
Let Register Pair HL equal 4300H.
NOTE: 4300H is a memory buffer (referred to as Memory Buffer 1) where diskette contents are stored in RAM.
NOTE: 4300H is the storage location for the 256 Byte Storage Area for Disk I/O.
4E67
LD (SAVE3),HL
Store the buffer pointer (held in Register Pair HL) into memory location 4EECH.
“LOOP0”
4E6A
LD HL,(SAVE3)
Fetch the current pointer to the current buffer (held in memory location 4EECH) and store it into Register Pair HL.
4E6D
LD A,(HL)
Fetch a character from the buffer (which is a character from the directory) and store it into Register A.
4E6E
OR A
We need to see if that first character of the directory entry is 0. Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
4E6F
JR Z,TOTNXT
     [4EBFH]
If the Z FLAG (Zero) has been set, then we have a blank file, so JUMP to 4EBFH to skip the file processing.
4E71
AND 48H
If we’re here then we found a file, but now need to see if it is a SYSTEM or INVISIBLE file. MASK the value of Register A against 48H (0100 1000) leaving only bits 6 and 3 active.
4E73
JR NZ,TOTNXT
      [4EBFH]
If the NZ FLAG (Not Zero) has been set, then we have either a SYSTEM or an INVISIBLE file, so JUMP to 4EBFH to skip the file processing.
4E75
LD B,08H
Let Register B equal the maximum length of a filename (i.e., 08H).
4E77
LD C,0FH
Let Register C equal the maximum length of a full filespec (i.e., 0FH or 15 characters).
4E79
4E7A
4E7C
LD A,L
ADD A,05H
LD L,A
LET Register Pair HL = Register Pair HL + 05H so as to push HL to the beginning of the filename.
“LOOP1”
4E7D
LD A,(HL)
Fetch a character from the filename (which is what HL is pointing to in the directory in the buffer).
4E7E
INC HL
Bump the buffer to point to the next character in the filename.
4E7F
CP 20H
We need to see if we are at the end of the filename, so compare that character against a SPACE. Results: If it is a SPACE, the Z FLAG will be set.
4E81
JR Z,OUT0
     [4E89H]
If it is a SPACE, then we are done processing filename characters so JUMP to 4E89H.
4E83
CALL 0033H
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4E86
DEC C
DECrement the filespec character counter stored in Register C by 1.
4E87
DJNZ LOOP1
     [4E7DH]
Keep processing characters by LOOPing back to 4E7DH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
“OUT0”
4E89
LD A,B
Copy the filename counter (held in Register B as the counter for the DJNZ loop) into Register A.
4E8A
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
4E8B
JR Z,OUT1
     [4E91H]
If B was zero, then we don’t need to fill the remaining characters of a filename (i.e., we got 8), so JUMP to 4E91H.
4E8D
DEC HL
Back up the pointer in the directory sector (value stored in Register Pair HL) by 1 in preparation for the following loop which starts by INCrementing it right back.
“OUT00”
4E8E
INC HL
INCrement the value stored in Register Pair HL by 1.
4E8F
DJNZ OUT00
     [4E8EH]
Keep skipping spaces by LOOPing back to 4E8EH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.

At this point, HL is now positioned at the file’s EXTENSION in the directory sector.

“OUT1”
4E91
LD A,(HL)
Fetch the first character of where the file’s extension is supposed to be in the directory entry held in RAM (pointed to by Register Pair HL) and store it into Register A.
4E92
CP 20H
Compare the value held in Register A against a SPACE). Results: If Register A equals SPACE, the Z FLAG is set; otherwise the NZ FLAG is set.
4E94
JR Z,OUT2
     [4EA6H]
If that very first character is a SPACE, then we know that there is no extension present; so skip processing the extension by JUMPing to 4EA6H.
4E96
LD A,2FH
We know that there is an extension, so we need to display a /. Let Register A equal 2FH (ASCII: /).
4E98
CALL 0033H
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4E9B
DEC C
DECrement the total filespec counter (stored in Register C) by 1.
4E9C
LD B,03H
Let Register B equal 03H for the length of an extension.
“LOOP2”
4E9E
LD A,(HL)
Fetch a character of where the file’s extension is supposed to be in the directory entry held in RAM (pointed to by Register Pair HL) and store it into Register A.
4E9F
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next character in the extension.
4EA0
CALL 0033H
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4EA3
DEC C
DECrement the total filespec counter (stored in Register C) by 1.
4EA4
DJNZ LOOP2
     [4E9EH]
Display the entire extension by LOOPing back to 4E9EH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
“OUT2”
4EA6
LD B,C
Copy the total number of characters left into Register B.
“LOOP3”
4EA7
LD A,20H
Let Register A equal 20H so that we can display the appropriate number of SPACE‘s.
4EA9
CALL 0033H
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4EAC
DJNZ LOOP3
     [4EA7H]
LOOP back to 4EA7H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
4EAE
LD A,(NUM)
Fetch the number of filenames that have already been displayed on the same line on screen (held in memory location 4EEFH) and store it into Register A.
4EB1
INC A
INCrement the value stored in Register A by 1 to indicate that one more was just displayed.
4EB2
CP 04H
Compare the value held in Register A against 04H to see if we already have 4. If A < 04H, the CARRY FLAG will be set.
4EB4
JR C,NXTNAM
     [4EBCH]
If we are less than 4, then we can keep displaying on this line, so JUMP down to 4EBCH.

If we are here, then we have already displayed 4 filenames on a line, so we need to end that line and reset everything that monitors that count and start again.

4EB6
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
4EB8
CALL 0033H
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4EBB
XOR A
Set Register A to ZERO in preparation for resetting the “how many filenames have appeared on screen on this line” tracker.
“NXTNAM”
4EBC
LD (NUM),A
Store the value held in Register A into the “how many filenames have appeared on screen on this line” tracker (held in memory location 4EEFH).
“TOTNXT”
4EBF
LD HL,(SAVE3)
Fetch the BUFFER starting location (held in memory location 4EECH) and store it into Register Pair HL.
4EC2
LD A,L
ADD A,30H
LD L,A
Let Register Pair HL point to the next filename in the buffer in RAM by advancing it 30H more bytes.
4EC6
LD (SAVE3),HL
Store the revised pointer to the directory sector in RAM into memory location 4EECH.
4EC9
CP 0F0H
Compare the value held in Register A against 0F0H, which is the delimeter for the last entry in a directory sector. If A < 0F0H, the CARRY FLAG will be set.
4ECB
JR C,4E6AH
     [4E6AH]
If the C FLAG (Carry) has been set, then we are not yet at the end of the sector, so JUMP back to 4E6AH to process the next filename.

If we are here, then we have exhausted all filenames in the current sector, and need to move to the next sector of the directory.

4ECD
LD A,(S10SEC)
Fetch the sector number of the directory which we just worked on from memory location 4EEEH.
4ED0
CP 13H
Compare the value held in Register A against 13H (Decimal: 19) to see if we have run out of sectors. If the sector we are on (held in Register A) < 19 sectors, the CARRY FLAG will be set.
4ED2
JP C,DIRLO2
     [4E4BH]
If the C FLAG (Carry) has been set then we have not yet hit sector 19, so loop back to 4E4BH to get the next directory sector.
4ED5
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
4ED7
JP 0033H
   [0033H]
JUMP to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.

4EDAH – BYTE STORAGE.

“DRIVE”
4EDA
DEFB 00H
Storage byte for the DRIVE NUMBER being worked on.
“TRK”
4EDB
DEFB 00H
Storage byte for the DIRECTORY TRACK of the disk in the DRIVE.
“DRVMSG”
4EDC
DEFM ‘DRIVE :’
“DRV”
4EE3
DEFM ‘0 ‘ + 03H
“SAVE3”
4EEC
DEFW 0000H
Location of the current pointer in the Directory Buffer in RAM
“S10SEC”
4EEE
DEFB 00H
The sector number in the directory being worked on.
“NUM”
4EEF
DEFB 00H
Number of filenames which have already appeared on screen on the current line.

4EF0H – Process an Error.

“DOERR”
4EF0
LD A,E
Copy the error code (held in Register E) into Register A.
4EF1
CP 8BH
Compare the value held in Register A against 8BH (Decimal: 139), which is the highest possible error code. If A >= 8BH, the NO CARRY FLAG will be set.
4EF3
JR NC,START1
      [4EFDH]
If the requested error code is higher than the highest possible error code then the NC FLAG (No Carry) will have been set, JUMP to 4EFDH to handle an UNPRINTABLE ERROR.
4EF5
CP 63H
Compare the value held in Register A against 63H (Decimal: 99), which is the start of the DISK ERRORs. If A >= 63H, the NO CARRY FLAG will be set.
4EF7
JR NC,START2
      [4EFFH]
If the requested error code is equal to or higher than 63H, then we have a disk error, so JUMP to 4EFFH.
4EF9
CP 2FH
Compare the value held in Register A against 2FH (Decimal: 47). If A < 2FH, the CARRY FLAG will be set.
4EFB
JR C,START3
     [4F01H]
If the C FLAG (Carry) has been set, JUMP to 4F01H.

If we pass through, then we wind up at the UNPRINTABLE ERROR jump point. How clever!

“START1”
4EFD
LD A,5AH
As a jump point, this processes an UNPRINTABLE ERROR. Let Register A equal 5AH (Decimal: 90) to set up to force an UNPRINTABLE ERROR after all the math that’s coming up.
“START2”
4EFF
SUB 34H
As a jump point, this processes disk errors. SUBtract the value 34H (Decimal: 52) from Register A. If passed through, then A now equals 5AH-34H=26H (Decimal 38). If jumped, A is between 63H-34H=2F (Decimal 47) and 8AH-34H=56H (Decimal 86).
“START3”4F01
RRCA
As a jump point, this is for errors 2EH (46 decimal) and below. Rotate the bits in A right, with Bit 0 being copied to both the CARRY FLAG and Bit 7. If passed from START 1, then 00100110 rotated to 00010011 (13H / 19).
4F02
INC A
INCrement the adjusted error code (stored in Register A) by 1. If this was from START 1, then A now is 20, meaning the 20th error. This is, in fact, 505AH which is UNPRINTABLE ERROR.
4F03
LD B,A
Copy the contents of Register A into Register B.
4F04
LD HL,ERRSTR
Let Register Pair HL equal 4F11H to point to the ERROR MESSAGE TABLE.

At this point, Register B is holding the number of error messages we need to skip before we get to the one we want.

“START4”
4F07
LD A,(HL)
Fetch a character from the error message table (the memory location pointed to by Register Pair HL) and store it into Register A.
4F08
INC HL
Point the to next character in the error message table by INCrementing the value stored in Register Pair HL by 1.
4F09
OR A
Set FLAGS based on the contents of Register A.
4F0A
JR NZ,START4
      [4F07H]
If we have no 0, then we have not yet reached the end of the error message, so LOOP back to START4.

We fall through to here when an entire error message has been read and its time to move to the next one.

4F0C
DJNZ START4
     [4F07H]
LOOP back to 4F07H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
4F0E
JP 1A01H
   [1A01H]
JUMP to the error handler at 1A01H.

4F11H – ERROR MESSAGE STORAGE AREA.

“ERRSTR”
4F11
DEFB 00H
Delimeter
4F12
DEFM ‘NEXT without FOR’
4F22
DEFB 00H
Delimeter
4F23
DEFM ‘Syntax Error’
4F2F
DEFB 00H
Delimeter
4F30
DEFM ‘RETURN without GOSUB’
4F44
DEFB 00H
Delimeter
4F45
DEFM ‘Out of DATA’
4F50
DEFB 00H
Delimeter
4F51
DEFM ‘Illegal function call’
4F66
DEFB 00H
Delimeter
4F67
DEFM ‘Overflow’
4F6F
DEFB 00H
Delimeter
4F70
DEFM ‘Out of memory’
4F7D
DEFB 00H
Delimeter
4F7E
DEFM ‘Undefined line number’
4F93
DEFB 00H
Delimeter
4F94
DEFM ‘Subscript out of range’
4FAA
DEFB 00H
Delimeter
4FAB
DEFM ‘Redimensioned array’
4FBE
DEFB 00H
Delimeter
4FBF
DEFM ‘Division by zero’
4FCF
DEFB 00H
Delimeter
4FD0
DEFM ‘Illegal direct’
4FDE
DEFB 00H
Delimeter
4FDF
DEFM ‘Type mismatch’
4FEC
DEFB 00H
Delimeter
4FED
DEFM ‘Out of string space’
5000
DEFB 00H
Delimeter
5001
DEFM ‘String too long’
5010
DEFB 00H
Delimeter
5011
DEFM ‘String formula too complex’
502B
DEFB 00H
Delimeter
502C
DEFM ‘Can’t Continue’
503A
DEFB 00H
Delimeter
503B
DEFM ‘No RESUME’
5044
DEFB 00H
Delimeter
5045
DEFM ‘RESUME without error’
5059
DEFB 00H
Delimeter
505A
DEFM ‘Unprintable error’
506B
DEFB 00H
Delimeter
506C
DEFM ‘Missing operand’
507B
DEFB 00H
Delimeter
507C
DEFM ‘BAD File Data’
5089
DEFB 00H
Delimeter
508A
DEFM ‘Disk Basic Feature’
509C
DEFB 00H
Delimeter
509D
DEFM ‘Undefined User Function’
50B4
DEFB 00H
Delimeter
50B5
DEFM ‘FIELD overflow’
50C3
DEFB 00H
Delimeter
50C4
DEFM ‘Internal error’
50D2
DEFB 00H
Delimeter
50D3
DEFM ‘Bad field number’
50E2
DEFB 00H
Delimeter
50E3
DEFM ‘File not found’
50F1
DEFB 00H
Delimeter
50F2
DEFM ‘Bad file mode’
50FF
DEFB 00H
Delimeter
5100
DEFM ‘File already open’
5111
DEFB 00H
Delimeter
5112
DEFM ‘?’
5113
DEFB 00H
Delimeter
5114
DEFM ‘Disk I/O error’
5122
DEFB 00H
Delimeter
5123
DEFM ‘File already exists’
5136
DEFB 00H
Delimeter
5137
DEFM ‘?’
5138
DEFB 00H
Delimeter
5139
DEFM ‘?’
513A
DEFB 00H
Delimeter
513B
DEFM ‘Disk full’
5144
DEFB 00H
Delimeter
5145
DEFM ‘Input past end’
5153
DEFB 00H
Delimeter
5154
DEFM ‘Bad record number’
5165
DEFB 00H
Delimeter
5166
DEFM ‘Bad filename’
5173
DEFB 00H
Delimeter
5174
DEFM ‘Mode mismatch’
5181
DEFB 00H
Delimeter
5182
DEFM ‘Direct statement in file’
519A
DEFB 00H
Delimeter
519B
DEFM ‘Too many files’
51A9
DEFB 00H
Delimeter
51AA
DEFM ‘Disk write protected’
51BE
DEFB 00H
Delimeter
51BF
DEFM ‘File access DENIED’
51D1
DEFB 00H
Delimeter
 
END 4E00H